mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-29 10:09:26 +02:00
Compare commits
18 Commits
mobile-rel
...
ui/rewrap-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15390ca8e6 | ||
|
|
e636b71ef2 | ||
|
|
108bf75081 | ||
|
|
aadb6e3a01 | ||
|
|
7c3fdab6ee | ||
|
|
14f727d6e6 | ||
|
|
688a646181 | ||
|
|
7a7f0db941 | ||
|
|
96be35c105 | ||
|
|
36bacce3ac | ||
|
|
c89e333c11 | ||
|
|
d521eb3bd8 | ||
|
|
20bf090c7e | ||
|
|
6cc9b8d1e1 | ||
|
|
e931423eba | ||
|
|
743d47e9e9 | ||
|
|
37c96177a7 | ||
|
|
3aa23d3215 |
9
.github/workflows/desktop.publish.yml
vendored
9
.github/workflows/desktop.publish.yml
vendored
@@ -107,7 +107,7 @@ jobs:
|
||||
target_commitish: ${{ github.ref }}
|
||||
|
||||
- name: Generate flatpak sources
|
||||
if: inputs.publish-github && inputs.build-linux
|
||||
if: inputs.build-linux
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --quiet flatpak flatpak-builder pipx
|
||||
@@ -127,6 +127,13 @@ jobs:
|
||||
files: ./generated-sources.json
|
||||
prerelease: ${{ endsWith(steps.app_metadata.outputs.app_version, '-beta') }}
|
||||
|
||||
- name: Upload generated-sources.json as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
if: inputs.build-linux
|
||||
with:
|
||||
name: generated-sources
|
||||
path: ./generated-sources.json
|
||||
|
||||
build-macos:
|
||||
name: Build for macOS
|
||||
needs: build
|
||||
|
||||
10291
apps/desktop/package-lock.json
generated
10291
apps/desktop/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
"name": "@notesnook/desktop",
|
||||
"productName": "Notesnook",
|
||||
"description": "Your private note taking space",
|
||||
"version": "3.4.2",
|
||||
"version": "3.4.3",
|
||||
"appAppleId": "1544027013",
|
||||
"private": true,
|
||||
"main": "./dist/cjs/index.js",
|
||||
@@ -59,7 +59,7 @@
|
||||
"@types/node": "22.15.3",
|
||||
"@types/yargs": "^17.0.33",
|
||||
"chokidar": "^4.0.3",
|
||||
"electron": "^37.0.0",
|
||||
"electron": "^37.10.3",
|
||||
"electron-builder": "^26.8.1",
|
||||
"esbuild": "0.21.5",
|
||||
"fkill": "^10.0.3",
|
||||
|
||||
@@ -140,7 +140,7 @@ android {
|
||||
if (project.hasProperty("prBuildNumber")) {
|
||||
versionCode Integer.parseInt(prBuildNumber())
|
||||
} else {
|
||||
versionCode 3109
|
||||
versionCode 3111
|
||||
}
|
||||
versionName getNpmVersion()
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
- Inbox API is now in beta. Learn more about it at https://help.notesnook.com/inbox-api/getting-started
|
||||
- Added close all tabs button in editor
|
||||
- Deeplinking support for nn:// urls
|
||||
- Set default image compression mode in Settings -> Behavior
|
||||
- Minor bug fixes and performance improvements
|
||||
- Minor bug fixes and improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
|
||||
@@ -39,6 +39,7 @@ import Share from "react-native-share";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
import FileViewer from "react-native-file-viewer";
|
||||
|
||||
const ImagePreview = () => {
|
||||
const { colors } = useThemeColors("dialog");
|
||||
@@ -87,9 +88,8 @@ const ImagePreview = () => {
|
||||
return;
|
||||
}
|
||||
const attachment = await db.attachments.attachment(hash);
|
||||
const path = `${cacheDir}/${
|
||||
"NN_" + (await getFileNameWithExtension(hash, attachment?.mimeType))
|
||||
}`;
|
||||
const path = `${cacheDir}/${"NN_" + (await getFileNameWithExtension(hash, attachment?.mimeType))
|
||||
}`;
|
||||
await RNFetchBlob.fs.mv(`${cacheDir}/${uri}`, path).catch(() => {
|
||||
/* empty */
|
||||
});
|
||||
@@ -136,17 +136,23 @@ const ImagePreview = () => {
|
||||
borderWidth: 0
|
||||
}}
|
||||
onPress={async () => {
|
||||
useSettingStore
|
||||
.getState()
|
||||
.setAppDidEnterBackgroundForAction(true);
|
||||
await Share.open({
|
||||
url: image
|
||||
}).catch(() => {
|
||||
/* empty */
|
||||
});
|
||||
useSettingStore
|
||||
.getState()
|
||||
.setAppDidEnterBackgroundForAction(false);
|
||||
if (!image) return;
|
||||
|
||||
try {
|
||||
if (Platform.OS === "android") {
|
||||
await FileViewer.open(image.replace("file://", ""), {
|
||||
showOpenWithDialog: true,
|
||||
showAppsSuggestions: true,
|
||||
shareFile: true
|
||||
} as any);
|
||||
} else {
|
||||
await Share.open({
|
||||
url: image
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<IconButton
|
||||
|
||||
@@ -156,7 +156,8 @@ export function MenuItem({
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: DefaultAppStyles.GAP_SMALL
|
||||
gap: DefaultAppStyles.GAP_SMALL,
|
||||
flexShrink: 1
|
||||
}}
|
||||
>
|
||||
{renderIcon ? (
|
||||
@@ -185,6 +186,7 @@ export function MenuItem({
|
||||
isFocused ? colors.selected.paragraph : colors.primary.paragraph
|
||||
}
|
||||
size={AppFontSize.sm}
|
||||
style={{ flexShrink: 1 }}
|
||||
>
|
||||
{item.title}
|
||||
</Paragraph>
|
||||
@@ -195,6 +197,9 @@ export function MenuItem({
|
||||
color={
|
||||
isFocused ? colors.primary.paragraph : colors.secondary.paragraph
|
||||
}
|
||||
style={{
|
||||
marginLeft: DefaultAppStyles.GAP_SMALL
|
||||
}}
|
||||
>
|
||||
{menuItemCount}
|
||||
</Paragraph>
|
||||
|
||||
@@ -72,7 +72,7 @@ export const NotebookItem = ({
|
||||
const notebook = item.notebook;
|
||||
const isFocused = focused;
|
||||
const { totalNotes, getTotalNotes } = useTotalNotes("notebook");
|
||||
const updater = useRelationStore(state => state.updater);
|
||||
const updater = useRelationStore((state) => state.updater);
|
||||
const getTotalNotesRef = React.useRef(getTotalNotes);
|
||||
getTotalNotesRef.current = getTotalNotes;
|
||||
const { colors } = useThemeColors();
|
||||
@@ -101,8 +101,8 @@ export const NotebookItem = ({
|
||||
item.depth === 0
|
||||
? undefined
|
||||
: item.depth < 6
|
||||
? 15 * item.depth
|
||||
: 15 * 5,
|
||||
? 15 * item.depth
|
||||
: 15 * 5,
|
||||
width: "100%",
|
||||
marginTop: 2,
|
||||
opacity: item.disabled ? 0.5 : 1
|
||||
@@ -162,7 +162,8 @@ export const NotebookItem = ({
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center"
|
||||
alignItems: "center",
|
||||
flexShrink: 1
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
@@ -191,8 +192,8 @@ export const NotebookItem = ({
|
||||
!item.hasChildren || disableExpand
|
||||
? "book-outline"
|
||||
: expanded
|
||||
? "chevron-down"
|
||||
: "chevron-right"
|
||||
? "chevron-down"
|
||||
: "chevron-right"
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -201,6 +202,7 @@ export const NotebookItem = ({
|
||||
isFocused ? colors.selected.paragraph : colors.primary.paragraph
|
||||
}
|
||||
size={AppFontSize.sm}
|
||||
style={{ flexShrink: 1 }}
|
||||
>
|
||||
{notebook?.title}
|
||||
</Paragraph>
|
||||
@@ -211,7 +213,8 @@ export const NotebookItem = ({
|
||||
gap: DefaultAppStyles.GAP_SMALL,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center"
|
||||
justifyContent: "center",
|
||||
marginLeft: DefaultAppStyles.GAP_SMALL
|
||||
}}
|
||||
>
|
||||
{selectionEnabled ? (
|
||||
|
||||
@@ -56,7 +56,7 @@ const TagItem = (props: {
|
||||
const totalNotes = useTotalNotes("tag");
|
||||
const totalNotesRef = React.useRef(totalNotes);
|
||||
totalNotesRef.current = totalNotes;
|
||||
const updater = useRelationStore(state => state.updater);
|
||||
const updater = useRelationStore((state) => state.updater);
|
||||
|
||||
useEffect(() => {
|
||||
if (item?.id) {
|
||||
@@ -67,6 +67,8 @@ const TagItem = (props: {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
minHeight: 35,
|
||||
justifyContent: "center",
|
||||
paddingHorizontal: DefaultAppStyles.GAP,
|
||||
marginTop:
|
||||
(props.id as number) === 0 ? DefaultAppStyles.GAP_VERTICAL : 2
|
||||
@@ -123,7 +125,8 @@ const TagItem = (props: {
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center"
|
||||
alignItems: "center",
|
||||
flexShrink: 1
|
||||
}}
|
||||
>
|
||||
<View
|
||||
@@ -146,6 +149,9 @@ const TagItem = (props: {
|
||||
isFocused ? colors.selected.paragraph : colors.primary.paragraph
|
||||
}
|
||||
size={AppFontSize.sm}
|
||||
style={{
|
||||
flexShrink: 1
|
||||
}}
|
||||
>
|
||||
{item?.title}
|
||||
</Paragraph>
|
||||
@@ -173,6 +179,9 @@ const TagItem = (props: {
|
||||
<Paragraph
|
||||
size={AppFontSize.xxs}
|
||||
color={colors.secondary.paragraph}
|
||||
style={{
|
||||
marginLeft: DefaultAppStyles.GAP_SMALL
|
||||
}}
|
||||
>
|
||||
{totalNotes.totalNotes(item?.id)}
|
||||
</Paragraph>
|
||||
|
||||
@@ -163,7 +163,20 @@ const LinkNotebooks = (props: NavigationProps<"LinkNotebooks">) => {
|
||||
}, [noteIds]);
|
||||
|
||||
const onSave = async () => {
|
||||
const changedNotebooks = useNotebookSelectionStore.getState().selection;
|
||||
const selectionState = useNotebookSelectionStore.getState();
|
||||
const changedNotebooks = { ...selectionState.selection };
|
||||
|
||||
if (!selectionState.multiSelect) {
|
||||
for (const id in selectionState.initialState) {
|
||||
if (
|
||||
selectionState.initialState[id] === "selected" &&
|
||||
changedNotebooks[id] !== "selected"
|
||||
) {
|
||||
changedNotebooks[id] = "deselected";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const id in changedNotebooks) {
|
||||
const item = await db.notebooks.notebook(id);
|
||||
if (!item) continue;
|
||||
@@ -207,11 +220,11 @@ const LinkNotebooks = (props: NavigationProps<"LinkNotebooks">) => {
|
||||
rightButton={
|
||||
hasSelection
|
||||
? {
|
||||
name: "restore",
|
||||
onPress: () => {
|
||||
updateInitialSelectionState(noteIds);
|
||||
}
|
||||
name: "restore",
|
||||
onPress: () => {
|
||||
updateInitialSelectionState(noteIds);
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -398,7 +398,8 @@ const TagItem = ({
|
||||
flexDirection: "row",
|
||||
marginVertical: 5,
|
||||
justifyContent: "flex-start",
|
||||
height: 40
|
||||
minHeight: 40,
|
||||
alignItems: "center"
|
||||
}}
|
||||
onPress={() => {
|
||||
if (!tag) return;
|
||||
@@ -438,7 +439,9 @@ const TagItem = ({
|
||||
/>
|
||||
)}
|
||||
{tag ? (
|
||||
<Paragraph size={AppFontSize.sm}>{"#" + tag?.title}</Paragraph>
|
||||
<Paragraph style={{ flexShrink: 1 }} size={AppFontSize.sm}>
|
||||
{"#" + tag?.title}
|
||||
</Paragraph>
|
||||
) : (
|
||||
<View
|
||||
style={{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Production iOS build identifiers
|
||||
IOS_CURRENT_PROJECT_VERSION = 2187
|
||||
IOS_MARKETING_VERSION = 3.4.3
|
||||
IOS_CURRENT_PROJECT_VERSION = 2189
|
||||
IOS_MARKETING_VERSION = 3.4.5
|
||||
IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook
|
||||
IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget
|
||||
IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Production iOS build identifiers
|
||||
IOS_CURRENT_PROJECT_VERSION = 2187
|
||||
IOS_MARKETING_VERSION = 3.4.3
|
||||
IOS_CURRENT_PROJECT_VERSION = 2189
|
||||
IOS_MARKETING_VERSION = 3.4.5
|
||||
IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook
|
||||
IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget
|
||||
IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Staging iOS build identifiers
|
||||
IOS_CURRENT_PROJECT_VERSION = 2187
|
||||
IOS_MARKETING_VERSION = 3.4.3
|
||||
IOS_CURRENT_PROJECT_VERSION = 2189
|
||||
IOS_MARKETING_VERSION = 3.4.5
|
||||
IOS_MAIN_BUNDLE_ID = org.streetwriters.notesnook
|
||||
IOS_WIDGET_BUNDLE_ID = org.streetwriters.notesnook.notewidget
|
||||
IOS_SHARE_BUNDLE_ID = org.streetwriters.notesnook.share
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.5",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"scripts": {
|
||||
@@ -18,7 +18,7 @@
|
||||
"e2e-android": "detox test --configuration android.emu.release --detectOpenHandles",
|
||||
"e2e-android-debug": "detox test --configuration android.emu.debug --detectOpenHandles",
|
||||
"e2e-ios": "detox test -c ios.sim.release --detectOpenHandles",
|
||||
"bump": "npx react-native bump-version --skip-semver-for android",
|
||||
"bump": "node ./scripts/bump-version.mjs",
|
||||
"release-android": "cd android && GITHUB_RELEASE=true ENVFILE=.env.public ./gradlew assembleRelease --no-daemon",
|
||||
"release-android-bundle": "cd android && ./gradlew bundleRelease --no-daemon",
|
||||
"lint": "eslint --ext .js,.jsx,.tsx,.ts ./app"
|
||||
|
||||
194
apps/mobile/scripts/bump-version.mjs
Normal file
194
apps/mobile/scripts/bump-version.mjs
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
|
||||
const PROJECT_ROOT = path.resolve(
|
||||
new URL(import.meta.url).pathname,
|
||||
"..",
|
||||
".."
|
||||
); // scripts/.. -> mobile
|
||||
|
||||
const REPO_ROOT = path.resolve(PROJECT_ROOT, "..", ".."); // mobile/../.. -> repo root
|
||||
const IOS_BUILD_CONFIGS_DIR = path.resolve(PROJECT_ROOT, "ios/build-configs");
|
||||
const ANDROID_GRADLE = path.resolve(PROJECT_ROOT, "android/app/build.gradle");
|
||||
const PACKAGE_JSON = path.resolve(PROJECT_ROOT, "package.json");
|
||||
const FDROID_CHANGELOGS_DIR = path.resolve(
|
||||
REPO_ROOT,
|
||||
"fastlane/metadata/android/en-US/changelogs"
|
||||
);
|
||||
|
||||
async function resolveVersion() {
|
||||
const provided = process.argv[2];
|
||||
if (provided) {
|
||||
if (!/^\d+\.\d+\.\d+$/.test(provided)) {
|
||||
console.error(`Invalid version "${provided}". Expected format: x.y.z`);
|
||||
process.exit(1);
|
||||
}
|
||||
return provided;
|
||||
}
|
||||
// No version provided: bump the current package.json version as a patch.
|
||||
const pkg = JSON.parse(await fs.readFile(PACKAGE_JSON, "utf8"));
|
||||
const match = String(pkg.version).match(/^(\d+)\.(\d+)\.(\d+)$/);
|
||||
if (!match) {
|
||||
console.error(
|
||||
`Cannot auto-bump: package.json version "${pkg.version}" is not x.y.z`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
const [, major, minor, patch] = match;
|
||||
return `${major}.${minor}.${Number(patch) + 1}`;
|
||||
}
|
||||
|
||||
const version = await resolveVersion();
|
||||
|
||||
async function updatePackageJson() {
|
||||
const raw = await fs.readFile(PACKAGE_JSON, "utf8");
|
||||
const pkg = JSON.parse(raw);
|
||||
const from = pkg.version;
|
||||
pkg.version = version;
|
||||
// Preserve trailing newline if present.
|
||||
const trailingNewline = raw.endsWith("\n") ? "\n" : "";
|
||||
await fs.writeFile(
|
||||
PACKAGE_JSON,
|
||||
JSON.stringify(pkg, null, 2) + trailingNewline
|
||||
);
|
||||
console.log(`package.json: version ${from} -> ${version}`);
|
||||
}
|
||||
|
||||
async function updateAndroid() {
|
||||
let content = await fs.readFile(ANDROID_GRADLE, "utf8");
|
||||
const match = content.match(/versionCode\s+(\d+)/);
|
||||
if (!match) {
|
||||
throw new Error("Could not find `versionCode <number>` in build.gradle");
|
||||
}
|
||||
const current = parseInt(match[1], 10);
|
||||
const next = current + 1;
|
||||
content = content.replace(match[0], `versionCode ${next}`);
|
||||
await fs.writeFile(ANDROID_GRADLE, content);
|
||||
console.log(`android/app/build.gradle: versionCode ${current} -> ${next}`);
|
||||
return next;
|
||||
}
|
||||
|
||||
// Derives the F-Droid release version code from build.gradle. F-Droid builds a
|
||||
// separate APK per ABI (see `applicationVariants.all` in build.gradle) using:
|
||||
// output.versionCodeOverride = defaultConfig.versionCode * <mult> + versionCodes[abi]
|
||||
// and publishes the highest of those. So the changelog file is named after
|
||||
// `versionCode * <mult> + max(versionCodes)`. Both are parsed here rather than
|
||||
// hardcoded so this stays in sync with the formula in build.gradle.
|
||||
async function computeFdroidVersionCode(versionCode) {
|
||||
const gradle = await fs.readFile(ANDROID_GRADLE, "utf8");
|
||||
|
||||
const multMatch = gradle.match(/defaultConfig\.versionCode\s*\*\s*(\d+)/);
|
||||
if (!multMatch) {
|
||||
throw new Error(
|
||||
"Could not find the F-Droid versionCode multiplier in build.gradle"
|
||||
);
|
||||
}
|
||||
const multiplier = parseInt(multMatch[1], 10);
|
||||
|
||||
const mapMatch = gradle.match(/versionCodes\s*=\s*\[([^\]]*)\]/);
|
||||
if (!mapMatch) {
|
||||
throw new Error("Could not find the ABI versionCodes map in build.gradle");
|
||||
}
|
||||
const abiCodes = [...mapMatch[1].matchAll(/:\s*(\d+)/g)].map((m) =>
|
||||
parseInt(m[1], 10)
|
||||
);
|
||||
if (abiCodes.length === 0) {
|
||||
throw new Error("ABI versionCodes map in build.gradle is empty");
|
||||
}
|
||||
const maxAbiCode = Math.max(...abiCodes);
|
||||
|
||||
return versionCode * multiplier + maxAbiCode;
|
||||
}
|
||||
|
||||
async function createFdroidChangelog(versionCode) {
|
||||
const fdroidVersionCode = await computeFdroidVersionCode(versionCode);
|
||||
const file = path.resolve(FDROID_CHANGELOGS_DIR, `${fdroidVersionCode}.txt`);
|
||||
const rel = path.relative(REPO_ROOT, file);
|
||||
|
||||
try {
|
||||
await fs.access(file);
|
||||
console.log(`${rel}: already exists, skipped`);
|
||||
return;
|
||||
} catch {
|
||||
// File does not exist yet — create it.
|
||||
}
|
||||
|
||||
const placeholder = "- Minor bug fixes and improvements\n\nThank you for using Notesnook!\n";
|
||||
await fs.mkdir(FDROID_CHANGELOGS_DIR, { recursive: true });
|
||||
await fs.writeFile(file, placeholder);
|
||||
console.log(`${rel}: created (edit with this release's changelog)`);
|
||||
}
|
||||
|
||||
async function updateIosConfig(file) {
|
||||
let content = await fs.readFile(file, "utf8");
|
||||
const rel = path.relative(PROJECT_ROOT, file);
|
||||
|
||||
const buildMatch = content.match(/IOS_CURRENT_PROJECT_VERSION\s*=\s*(\d+)/);
|
||||
if (!buildMatch) {
|
||||
throw new Error(`Could not find IOS_CURRENT_PROJECT_VERSION in ${rel}`);
|
||||
}
|
||||
const currentBuild = parseInt(buildMatch[1], 10);
|
||||
const nextBuild = currentBuild + 1;
|
||||
content = content.replace(
|
||||
buildMatch[0],
|
||||
`IOS_CURRENT_PROJECT_VERSION = ${nextBuild}`
|
||||
);
|
||||
|
||||
const marketingMatch = content.match(/IOS_MARKETING_VERSION\s*=\s*(\S+)/);
|
||||
if (!marketingMatch) {
|
||||
throw new Error(`Could not find IOS_MARKETING_VERSION in ${rel}`);
|
||||
}
|
||||
const currentMarketing = marketingMatch[1];
|
||||
content = content.replace(
|
||||
marketingMatch[0],
|
||||
`IOS_MARKETING_VERSION = ${version}`
|
||||
);
|
||||
|
||||
await fs.writeFile(file, content);
|
||||
console.log(
|
||||
`${rel}: version ${currentMarketing} -> ${version}, build ${currentBuild} -> ${nextBuild}`
|
||||
);
|
||||
}
|
||||
|
||||
async function updateIos() {
|
||||
const entries = await fs.readdir(IOS_BUILD_CONFIGS_DIR);
|
||||
const configs = entries.filter((e) => e.endsWith(".xcconfig"));
|
||||
if (configs.length === 0) {
|
||||
throw new Error("No .xcconfig files found in ios/build-configs");
|
||||
}
|
||||
for (const config of configs) {
|
||||
await updateIosConfig(path.resolve(IOS_BUILD_CONFIGS_DIR, config));
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
console.log(`Bumping to version ${version}...\n`);
|
||||
await updatePackageJson();
|
||||
const androidVersionCode = await updateAndroid();
|
||||
await updateIos();
|
||||
await createFdroidChangelog(androidVersionCode);
|
||||
console.log("\nDone.");
|
||||
}
|
||||
|
||||
run().catch((err) => {
|
||||
console.error("Failed:", err?.message || err);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
4
apps/web/package-lock.json
generated
4
apps/web/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"version": "3.4.2",
|
||||
"version": "3.4.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/web",
|
||||
"version": "3.4.2",
|
||||
"version": "3.4.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"description": "Your private note taking space",
|
||||
"version": "3.4.2",
|
||||
"version": "3.4.3",
|
||||
"private": true,
|
||||
"main": "./src/app.js",
|
||||
"homepage": "https://notesnook.com/",
|
||||
|
||||
@@ -496,6 +496,7 @@ export const noteMenuItems: (
|
||||
"text/html": `<a href="${url}">${note.title}</a>`,
|
||||
"text/markdown": `[${note.title}](${url})`
|
||||
});
|
||||
showToast("success", strings.linkCopied());
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -594,6 +595,7 @@ export const noteMenuItems: (
|
||||
"text/html": `<a href="${link}">${note.title}</a>`,
|
||||
"text/markdown": `[${note.title}](${link})`
|
||||
});
|
||||
showToast("success", strings.linkCopied());
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -115,7 +115,7 @@ export function UnlockView(props: UnlockViewProps) {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{isWrong && <ErrorText error="Wrong password" />}
|
||||
{isWrong && <ErrorText sx={{ mt: 1 }} error="Wrong password" />}
|
||||
<Button
|
||||
mt={3}
|
||||
variant="accent"
|
||||
|
||||
@@ -97,34 +97,7 @@ const features: Record<FeatureKeys, Feature> = {
|
||||
)
|
||||
}
|
||||
]
|
||||
: [
|
||||
{
|
||||
icon: Inbox,
|
||||
title: "Inbox API",
|
||||
subtitle: "A new API to send data to Notesnook from other apps."
|
||||
},
|
||||
{
|
||||
icon: LinkedTo,
|
||||
title: "Deep links on Desktop",
|
||||
subtitle: "Reference Notesnook notes from other apps."
|
||||
},
|
||||
{
|
||||
icon: Plus,
|
||||
title: "More features, bug fixes, and security improvments",
|
||||
subtitle: (
|
||||
<>
|
||||
This release contains much much more.{" "}
|
||||
<Link
|
||||
href="https://blog.notesnook.com/notesnook-desktop-v3.4.0"
|
||||
target="_blank"
|
||||
title="Read the full release notes"
|
||||
>
|
||||
Read the full release notes
|
||||
</Link>
|
||||
</>
|
||||
)
|
||||
}
|
||||
],
|
||||
: [],
|
||||
cta: {
|
||||
title: strings.gotIt(),
|
||||
icon: Checkmark,
|
||||
|
||||
@@ -59,6 +59,9 @@ export const AuthenticationSettings: SettingsGroup[] = [
|
||||
}
|
||||
},
|
||||
validate: async ({ oldPassword, newPassword }) => {
|
||||
const verify = await db.user.verifyPassword(oldPassword);
|
||||
if (!verify) return false;
|
||||
|
||||
try {
|
||||
if (!(await createBackup({ noVerify: true }))) return false;
|
||||
return (
|
||||
|
||||
7
fastlane/metadata/android/en-US/changelogs/15554.txt
Normal file
7
fastlane/metadata/android/en-US/changelogs/15554.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
- Inbox API is now in beta. Learn more about it at https://help.notesnook.com/inbox-api/getting-started
|
||||
- Added close all tabs button in editor
|
||||
- Deeplinking support for nn:// urls
|
||||
- Set default image compression mode in Settings -> Behavior
|
||||
- Minor bug fixes and performance improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
3
fastlane/metadata/android/en-US/changelogs/15559.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/15559.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Minor bug fixes and improvements
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -437,6 +437,7 @@ export class Notes implements ICollection {
|
||||
const duplicateId = await this.db.notes.add({
|
||||
...clone(note),
|
||||
id: undefined,
|
||||
pinned: false,
|
||||
isGeneratedTitle: false,
|
||||
contentId: undefined,
|
||||
title: note.title + " (Copy)",
|
||||
|
||||
@@ -27,7 +27,17 @@ export function getFontSizes(): FontSizes {
|
||||
body: "12px",
|
||||
subBody: "10px",
|
||||
menu: "12px",
|
||||
code: "14px"
|
||||
code: "14px",
|
||||
xxxs: "10px",
|
||||
xxs: "11px",
|
||||
xs: "13px",
|
||||
sm: "15px",
|
||||
md: "17px",
|
||||
lg: "20px",
|
||||
xl: "25px",
|
||||
"2xl": "30px",
|
||||
"3xl": "35px",
|
||||
"4xl": "40px"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -41,4 +51,14 @@ export type FontSizes = {
|
||||
menu: string;
|
||||
subBody: string;
|
||||
code: string;
|
||||
xxxs: string;
|
||||
xxs: string;
|
||||
xs: string;
|
||||
sm: string;
|
||||
md: string;
|
||||
lg: string;
|
||||
xl: string;
|
||||
"2xl": string;
|
||||
"3xl": string;
|
||||
"4xl": string;
|
||||
};
|
||||
|
||||
@@ -27,7 +27,22 @@ export { createButtonVariant } from "./variants/button.js";
|
||||
export { getFontConfig } from "./font/index.js";
|
||||
export type Theme = {
|
||||
breakpoints: string[];
|
||||
space: (number | string)[] & { small?: number | string };
|
||||
space: (number | string)[] & {
|
||||
small?: number | string;
|
||||
spacing1: number;
|
||||
spacing2: number;
|
||||
spacing3: number;
|
||||
spacing4: number;
|
||||
spacing5: number;
|
||||
spacing6: number;
|
||||
spacing7: number;
|
||||
spacing8: number;
|
||||
spacing9: number;
|
||||
spacing10: number;
|
||||
spacing11: number;
|
||||
spacing12: number;
|
||||
spacing13: number;
|
||||
};
|
||||
sizes: { full: "100%"; half: "50%" };
|
||||
radii: {
|
||||
none: number;
|
||||
@@ -35,6 +50,15 @@ export type Theme = {
|
||||
dialog: number;
|
||||
large: number;
|
||||
small: number;
|
||||
radius1: number;
|
||||
radius2: number;
|
||||
radius3: number;
|
||||
radius4: number;
|
||||
radius5: number;
|
||||
radius6: number;
|
||||
radius7: number;
|
||||
radius8: number;
|
||||
radius9: number;
|
||||
};
|
||||
shadows: { menu: string };
|
||||
colors: Record<ThemeColor, string>;
|
||||
@@ -51,9 +75,38 @@ export class ThemeFactory {
|
||||
static construct(config: ThemeConfig): Theme {
|
||||
const theme: Theme = {
|
||||
breakpoints: ["480px", "1000px", "1000px"],
|
||||
space: [0, "6px", 10, 15, 20, 25, 30, 35],
|
||||
space: Object.assign([0, "6px", 10, 15, 20, 25, 30, 35], {
|
||||
spacing1: 3,
|
||||
spacing2: 5,
|
||||
spacing3: 7,
|
||||
spacing4: 10,
|
||||
spacing5: 13,
|
||||
spacing6: 15,
|
||||
spacing7: 20,
|
||||
spacing8: 25,
|
||||
spacing9: 30,
|
||||
spacing10: 35,
|
||||
spacing11: 40,
|
||||
spacing12: 45,
|
||||
spacing13: 50
|
||||
}),
|
||||
sizes: { full: "100%", half: "50%" },
|
||||
radii: { none: 0, default: 5, large: 7, dialog: 10, small: 2.5 },
|
||||
radii: {
|
||||
none: 0,
|
||||
default: 5,
|
||||
large: 7,
|
||||
dialog: 10,
|
||||
small: 2.5,
|
||||
radius1: 5,
|
||||
radius2: 10,
|
||||
radius3: 15,
|
||||
radius4: 20,
|
||||
radius5: 25,
|
||||
radius6: 30,
|
||||
radius7: 35,
|
||||
radius8: 40,
|
||||
radius9: 45
|
||||
},
|
||||
iconSizes: { big: 16, medium: 14, small: 12 },
|
||||
colors: flattenVariants(config.scope),
|
||||
shadows:
|
||||
|
||||
45
packages/ui/src/components/box.tsx
Normal file
45
packages/ui/src/components/box.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
Box as ThemeUIBox,
|
||||
BoxProps as ThemeUIBoxProps
|
||||
} from "@theme-ui/components";
|
||||
import { Theme } from "@notesnook/theme";
|
||||
import {
|
||||
RestrictedColorProps,
|
||||
RestrictedSpaceProps,
|
||||
RestrictedSxProp
|
||||
} from "../utils/types.js";
|
||||
|
||||
export interface BoxProps
|
||||
extends Omit<
|
||||
ThemeUIBoxProps,
|
||||
"variant" | "sx" | keyof RestrictedSpaceProps | keyof RestrictedColorProps
|
||||
>,
|
||||
RestrictedSpaceProps,
|
||||
RestrictedColorProps {
|
||||
variant?: keyof Theme["variants"];
|
||||
sx?: RestrictedSxProp;
|
||||
}
|
||||
|
||||
export const Box = React.forwardRef<HTMLDivElement, BoxProps>((props, ref) => {
|
||||
return <ThemeUIBox ref={ref} {...props} />;
|
||||
});
|
||||
47
packages/ui/src/components/button.tsx
Normal file
47
packages/ui/src/components/button.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
Button as ThemeUIButton,
|
||||
ButtonProps as ThemeUIButtonProps
|
||||
} from "@theme-ui/components";
|
||||
import { Theme } from "@notesnook/theme";
|
||||
import {
|
||||
RestrictedColorProps,
|
||||
RestrictedSpaceProps,
|
||||
RestrictedSxProp
|
||||
} from "../utils/types.js";
|
||||
|
||||
export interface ButtonProps
|
||||
extends Omit<
|
||||
ThemeUIButtonProps,
|
||||
"variant" | "sx" | keyof RestrictedSpaceProps | keyof RestrictedColorProps
|
||||
>,
|
||||
RestrictedSpaceProps,
|
||||
RestrictedColorProps {
|
||||
variant?: keyof Theme["buttons"];
|
||||
sx?: RestrictedSxProp;
|
||||
}
|
||||
|
||||
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
(props, ref) => {
|
||||
return <ThemeUIButton ref={ref} {...props} />;
|
||||
}
|
||||
);
|
||||
47
packages/ui/src/components/flex.tsx
Normal file
47
packages/ui/src/components/flex.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
Flex as ThemeUIFlex,
|
||||
FlexProps as ThemeUIFlexProps
|
||||
} from "@theme-ui/components";
|
||||
import { Theme } from "@notesnook/theme";
|
||||
import {
|
||||
RestrictedColorProps,
|
||||
RestrictedSpaceProps,
|
||||
RestrictedSxProp
|
||||
} from "../utils/types.js";
|
||||
|
||||
export interface FlexProps
|
||||
extends Omit<
|
||||
ThemeUIFlexProps,
|
||||
"variant" | "sx" | keyof RestrictedSpaceProps | keyof RestrictedColorProps
|
||||
>,
|
||||
RestrictedSpaceProps,
|
||||
RestrictedColorProps {
|
||||
variant?: keyof Theme["variants"];
|
||||
sx?: RestrictedSxProp;
|
||||
}
|
||||
|
||||
export const Flex = React.forwardRef<HTMLDivElement, FlexProps>(
|
||||
(props, ref) => {
|
||||
return <ThemeUIFlex ref={ref} {...props} />;
|
||||
}
|
||||
);
|
||||
@@ -21,3 +21,7 @@ export * from "./icon/index.js";
|
||||
export * from "./menu/index.js";
|
||||
export * from "./popup-presenter/index.js";
|
||||
export * from "./scroll-container/index.js";
|
||||
export * from "./button.js";
|
||||
export * from "./box.js";
|
||||
export * from "./flex.js";
|
||||
export * from "./slider.js";
|
||||
|
||||
47
packages/ui/src/components/slider.tsx
Normal file
47
packages/ui/src/components/slider.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import {
|
||||
Slider as ThemeUISlider,
|
||||
SliderProps as ThemeUISliderProps
|
||||
} from "@theme-ui/components";
|
||||
import { Theme } from "@notesnook/theme";
|
||||
import {
|
||||
RestrictedColorProps,
|
||||
RestrictedSpaceProps,
|
||||
RestrictedSxProp
|
||||
} from "../utils/types.js";
|
||||
|
||||
export interface SliderProps
|
||||
extends Omit<
|
||||
ThemeUISliderProps,
|
||||
"variant" | "sx" | keyof RestrictedSpaceProps | keyof RestrictedColorProps
|
||||
>,
|
||||
RestrictedSpaceProps,
|
||||
RestrictedColorProps {
|
||||
variant?: keyof Theme["forms"];
|
||||
sx?: RestrictedSxProp;
|
||||
}
|
||||
|
||||
export const Slider = React.forwardRef<HTMLInputElement, SliderProps>(
|
||||
(props, ref) => {
|
||||
return <ThemeUISlider ref={ref} {...(props as any)} />;
|
||||
}
|
||||
);
|
||||
@@ -18,3 +18,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export * from "./position.js";
|
||||
export * from "./types.js";
|
||||
|
||||
73
packages/ui/src/utils/types.ts
Normal file
73
packages/ui/src/utils/types.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Theme, ThemeColor } from "@notesnook/theme";
|
||||
import { ThemeUIStyleObject } from "@theme-ui/core";
|
||||
|
||||
type ThemeSpace = Theme["space"];
|
||||
|
||||
type ValidSpaceValues =
|
||||
| Exclude<keyof ThemeSpace, keyof Array<any> | "small">
|
||||
| "small"
|
||||
| number;
|
||||
|
||||
export type RestrictedColorProps = {
|
||||
color?: ThemeColor;
|
||||
bg?: ThemeColor | (ThemeColor | null)[];
|
||||
backgroundColor?: ThemeColor | (ThemeColor | null)[];
|
||||
};
|
||||
|
||||
export type RestrictedSpaceProps = {
|
||||
[K in
|
||||
| "m"
|
||||
| "mt"
|
||||
| "mr"
|
||||
| "mb"
|
||||
| "ml"
|
||||
| "mx"
|
||||
| "my"
|
||||
| "margin"
|
||||
| "marginTop"
|
||||
| "marginRight"
|
||||
| "marginBottom"
|
||||
| "marginLeft"
|
||||
| "marginX"
|
||||
| "marginY"
|
||||
| "p"
|
||||
| "pt"
|
||||
| "pr"
|
||||
| "pb"
|
||||
| "pl"
|
||||
| "px"
|
||||
| "py"
|
||||
| "padding"
|
||||
| "paddingTop"
|
||||
| "paddingRight"
|
||||
| "paddingBottom"
|
||||
| "paddingLeft"
|
||||
| "paddingX"
|
||||
| "paddingY"]?: ValidSpaceValues | (ValidSpaceValues | null)[];
|
||||
};
|
||||
|
||||
export type RestrictedSxProp = Omit<
|
||||
ThemeUIStyleObject,
|
||||
keyof RestrictedSpaceProps | keyof RestrictedColorProps
|
||||
> &
|
||||
RestrictedSpaceProps &
|
||||
RestrictedColorProps;
|
||||
Reference in New Issue
Block a user