feat: new widgets on android (#7311)

- Added a new widget on android that allows you to put a note on your home screen.
- Added a new widget on android that allows you to see upcoming reminders on home screen
- Fixed new note widget freezing
This commit is contained in:
Ammar Ahmed
2025-01-20 17:17:01 +05:00
committed by GitHub
parent aa993a2fce
commit a13cbadd44
105 changed files with 1758 additions and 356 deletions

View File

@@ -32,12 +32,14 @@ import { withErrorBoundry } from "./components/exception-handler";
import GlobalSafeAreaProvider from "./components/globalsafearea"; import GlobalSafeAreaProvider from "./components/globalsafearea";
import { useAppEvents } from "./hooks/use-app-events"; import { useAppEvents } from "./hooks/use-app-events";
import { ApplicationHolder } from "./navigation"; import { ApplicationHolder } from "./navigation";
import { NotePreviewConfigure } from "./screens/note-preview-configure";
import { themeTrpcClient } from "./screens/settings/theme-selector"; import { themeTrpcClient } from "./screens/settings/theme-selector";
import Notifications from "./services/notifications"; import Notifications from "./services/notifications";
import SettingsService from "./services/settings"; import SettingsService from "./services/settings";
import { TipManager } from "./services/tip-manager"; import { TipManager } from "./services/tip-manager";
import { useThemeStore } from "./stores/use-theme-store"; import { useThemeStore } from "./stores/use-theme-store";
import { useUserStore } from "./stores/use-user-store"; import { useUserStore } from "./stores/use-user-store";
import { IntentService } from "./services/intent";
I18nManager.allowRTL(false); I18nManager.allowRTL(false);
I18nManager.forceRTL(false); I18nManager.forceRTL(false);
@@ -47,7 +49,8 @@ if (appLockEnabled || appLockMode !== "none") {
useUserStore.getState().lockApp(true); useUserStore.getState().lockApp(true);
} }
const App = () => { IntentService.onLaunch();
const App = (props: { configureMode: "note-preview" }) => {
useAppEvents(); useAppEvents();
//@ts-ignore //@ts-ignore
globalThis["IS_MAIN_APP_RUNNING"] = true; globalThis["IS_MAIN_APP_RUNNING"] = true;
@@ -61,6 +64,7 @@ const App = () => {
TipManager.init(); TipManager.init();
}, 100); }, 100);
}, []); }, []);
return ( return (
<View <View
style={{ style={{
@@ -90,7 +94,11 @@ const App = () => {
width: "100%" width: "100%"
}} }}
> >
<ApplicationHolder /> {props.configureMode === "note-preview" ? (
<NotePreviewConfigure />
) : (
<ApplicationHolder />
)}
</GestureHandlerRootView> </GestureHandlerRootView>
<AppLockedOverlay /> <AppLockedOverlay />
</View> </View>
@@ -103,8 +111,8 @@ let currTheme =
: SettingsService.getProperty("lighTheme"); : SettingsService.getProperty("lighTheme");
useThemeEngineStore.getState().setTheme(currTheme); useThemeEngineStore.getState().setTheme(currTheme);
export const withTheme = (Element: () => JSX.Element) => { export const withTheme = (Element: (props: any) => JSX.Element) => {
return function AppWithThemeProvider() { return function AppWithThemeProvider(props: any) {
const [colorScheme, darkTheme, lightTheme] = useThemeStore((state) => [ const [colorScheme, darkTheme, lightTheme] = useThemeStore((state) => [
state.colorScheme, state.colorScheme,
state.darkTheme, state.darkTheme,
@@ -123,13 +131,14 @@ export const withTheme = (Element: () => JSX.Element) => {
}) })
.then((theme) => { .then((theme) => {
if (theme) { if (theme) {
console.log(theme.version, "theme updated");
theme.colorScheme === "dark" theme.colorScheme === "dark"
? useThemeStore.getState().setDarkTheme(theme) ? useThemeStore.getState().setDarkTheme(theme)
: useThemeStore.getState().setLightTheme(theme); : useThemeStore.getState().setLightTheme(theme);
} }
}) })
.catch(console.log); .catch(() => {
/* empty */
});
}, 1000); }, 1000);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
@@ -144,7 +153,7 @@ export const withTheme = (Element: () => JSX.Element) => {
return ( return (
<I18nProvider i18n={i18n}> <I18nProvider i18n={i18n}>
<Element /> <Element {...props} />
</I18nProvider> </I18nProvider>
); );
}; };

View File

@@ -126,7 +126,6 @@ export async function setAppLockVerificationCipher(appLockPassword: string) {
DatabaseLogger.info("setAppLockVerificationCipher"); DatabaseLogger.info("setAppLockVerificationCipher");
} catch (e) { } catch (e) {
DatabaseLogger.error(e); DatabaseLogger.error(e);
console.log(e);
} }
} }
@@ -310,7 +309,6 @@ export async function getCryptoKey() {
return key; return key;
} catch (e) { } catch (e) {
console.log("getCryptoKey", e);
DatabaseLogger.error(e); DatabaseLogger.error(e);
} }
} }

View File

@@ -39,8 +39,6 @@ export async function setupDatabase(password?: string) {
const key = await getDatabaseKey(password); const key = await getDatabaseKey(password);
if (!key) throw new Error(strings.databaseSetupFailed()); if (!key) throw new Error(strings.databaseSetupFailed());
console.log("Opening database with key:", !!key);
database.host({ database.host({
API_HOST: "https://api.notesnook.com", API_HOST: "https://api.notesnook.com",
AUTH_HOST: "https://auth.streetwriters.co", AUTH_HOST: "https://auth.streetwriters.co",

View File

@@ -27,13 +27,9 @@ import RNFetchBlob from "react-native-blob-util";
*/ */
export async function compressToBase64(path, type) { export async function compressToBase64(path, type) {
const { width: screenWidth, scale } = Dimensions.get("window"); const { width: screenWidth, scale } = Dimensions.get("window");
console.log("COMPRESSING TO BASE64...");
return new Promise((resolve) => { return new Promise((resolve) => {
console.log(path, "image path...");
Image.getSize(path, async (width) => { Image.getSize(path, async (width) => {
console.log("image width", width);
const response = await ImageResizer.createResizedImage( const response = await ImageResizer.createResizedImage(
path, path,
screenWidth * scale, screenWidth * scale,
@@ -55,10 +51,12 @@ export async function compressToBase64(path, type) {
: response.uri, : response.uri,
"base64" "base64"
); );
RNFetchBlob.fs.unlink(path.replace("file://", "")).catch(console.log); RNFetchBlob.fs.unlink(path.replace("file://", "")).catch(() => {
RNFetchBlob.fs /* empty */
.unlink(response.uri.replace("file://", "")) });
.catch(console.log); RNFetchBlob.fs.unlink(response.uri.replace("file://", "")).catch(() => {
/* empty */
});
resolve(base64); resolve(base64);
}); });
@@ -80,6 +78,8 @@ export async function compressToFile(path, type) {
onlyScaleDown: true onlyScaleDown: true
} }
); );
RNFetchBlob.fs.unlink(path.replace("file://", "")).catch(console.log); RNFetchBlob.fs.unlink(path.replace("file://", "")).catch(() => {
/* empty */
});
return response.uri; return response.uri;
} }

View File

@@ -83,7 +83,9 @@ export async function downloadAttachments(attachmentIds: string[]) {
const isCancelled = () => { const isCancelled = () => {
if (useAttachmentStore.getState().downloading?.[groupId]?.canceled) { if (useAttachmentStore.getState().downloading?.[groupId]?.canceled) {
RNFetchBlob.fs.unlink(zipSourceFolder).catch(console.log); RNFetchBlob.fs.unlink(zipSourceFolder).catch(() => {
/* empty */
});
useAttachmentStore.getState().setDownloading({ useAttachmentStore.getState().setDownloading({
groupId, groupId,
current: 0, current: 0,
@@ -188,9 +190,13 @@ export async function downloadAttachments(attachmentIds: string[]) {
ToastManager.error(e as Error, "Error zipping attachments"); ToastManager.error(e as Error, "Error zipping attachments");
} }
// Remove source & zip file from cache. // Remove source & zip file from cache.
RNFetchBlob.fs.unlink(zipSourceFolder).catch(console.log); RNFetchBlob.fs.unlink(zipSourceFolder).catch(() => {
/* empty */
});
if (Platform.OS === "android") { if (Platform.OS === "android") {
RNFetchBlob.fs.unlink(zipOutputFile).catch(console.log); RNFetchBlob.fs.unlink(zipOutputFile).catch(() => {
/* empty */
});
} }
} }
@@ -295,8 +301,6 @@ export default async function downloadAttachment(
options?.cache ? "cache" : "file" options?.cache ? "cache" : "file"
); );
console.log("file URI", fileUri, options?.cache);
if (!options?.silent) { if (!options?.silent) {
ToastManager.show({ ToastManager.show({
heading: strings.network.downloadSuccess(), heading: strings.network.downloadSuccess(),
@@ -323,10 +327,14 @@ export default async function downloadAttachment(
if (attachment.dateUploaded) { if (attachment.dateUploaded) {
RNFetchBlob.fs RNFetchBlob.fs
.unlink(RNFetchBlob.fs.dirs.CacheDir + `/${attachment.hash}`) .unlink(RNFetchBlob.fs.dirs.CacheDir + `/${attachment.hash}`)
.catch(console.log); .catch(() => {
/* empty */
});
RNFetchBlob.fs RNFetchBlob.fs
.unlink(RNFetchBlob.fs.dirs.CacheDir + `/${attachment.hash}_dcache`) .unlink(RNFetchBlob.fs.dirs.CacheDir + `/${attachment.hash}_dcache`)
.catch(console.log); .catch(() => {
/* empty */
});
} }
useAttachmentStore.getState().setDownloading({ useAttachmentStore.getState().setDownloading({

View File

@@ -123,7 +123,9 @@ export async function downloadFile(
cancelToken.cancel = async (reason) => { cancelToken.cancel = async (reason) => {
useAttachmentStore.getState().remove(filename); useAttachmentStore.getState().remove(filename);
request.cancel(); request.cancel();
RNFetchBlob.fs.unlink(tempFilePath).catch(console.log); RNFetchBlob.fs.unlink(tempFilePath).catch(() => {
/* empty */
});
DatabaseLogger.log(`Download cancelled: ${reason} ${filename}`); DatabaseLogger.log(`Download cancelled: ${reason} ${filename}`);
}; };
@@ -142,7 +144,9 @@ export async function downloadFile(
useAttachmentStore.getState().remove(filename); useAttachmentStore.getState().remove(filename);
if (await exists(originalFilePath)) { if (await exists(originalFilePath)) {
await RNFetchBlob.fs.unlink(originalFilePath).catch(console.log); await RNFetchBlob.fs.unlink(originalFilePath).catch(() => {
/* empty */
});
} }
await RNFetchBlob.fs.mv(tempFilePath, originalFilePath); await RNFetchBlob.fs.mv(tempFilePath, originalFilePath);
@@ -169,8 +173,12 @@ export async function downloadFile(
} }
useAttachmentStore.getState().remove(filename); useAttachmentStore.getState().remove(filename);
RNFetchBlob.fs.unlink(tempFilePath).catch(console.log); RNFetchBlob.fs.unlink(tempFilePath).catch(() => {
RNFetchBlob.fs.unlink(originalFilePath).catch(console.log); /* empty */
});
RNFetchBlob.fs.unlink(originalFilePath).catch(() => {
/* empty */
});
DatabaseLogger.error(e, "Download failed: ", { DatabaseLogger.error(e, "Download failed: ", {
url url
}); });
@@ -188,7 +196,7 @@ export async function checkAttachment(hash: string) {
try { try {
const size = await getUploadedFileSize(hash); const size = await getUploadedFileSize(hash);
console.log("File Size", size);
if (size === -1) return { success: true }; if (size === -1) return { success: true };
if (size === 0) if (size === 0)

View File

@@ -60,7 +60,9 @@ export async function readEncrypted<TOutputFormat extends DataFormat>(
return output as Output<TOutputFormat>; return output as Output<TOutputFormat>;
} catch (e) { } catch (e) {
RNFetchBlob.fs.unlink(path).catch(console.log); RNFetchBlob.fs.unlink(path).catch(() => {
/* empty */
});
DatabaseLogger.error(e); DatabaseLogger.error(e);
} }
} }
@@ -90,8 +92,9 @@ export async function writeEncryptedBase64(
type: "url" type: "url"
}); });
RNFetchBlob.fs.unlink(filepath).catch(console.log); RNFetchBlob.fs.unlink(filepath).catch(() => {
console.log("encrypted file output: ", output); /* empty */
});
return { return {
...output, ...output,
@@ -106,7 +109,9 @@ export async function deleteFile(
await createCacheDir(); await createCacheDir();
const localFilePath = cacheDir + `/${filename}`; const localFilePath = cacheDir + `/${filename}`;
if (!requestOptions) { if (!requestOptions) {
RNFetchBlob.fs.unlink(localFilePath).catch(console.log); RNFetchBlob.fs.unlink(localFilePath).catch(() => {
/* empty */
});
return true; return true;
} }
@@ -117,7 +122,9 @@ export async function deleteFile(
const status = response.info().status; const status = response.info().status;
const ok = status >= 200 && status < 300; const ok = status >= 200 && status < 300;
if (ok) { if (ok) {
RNFetchBlob.fs.unlink(localFilePath).catch(console.log); RNFetchBlob.fs.unlink(localFilePath).catch(() => {
/* empty */
});
} }
return ok; return ok;
} catch (e) { } catch (e) {
@@ -134,10 +141,14 @@ export async function clearFileStorage() {
const oldCache = await RNFetchBlob.fs.ls(cacheDirOld); const oldCache = await RNFetchBlob.fs.ls(cacheDirOld);
for (const file of files) { for (const file of files) {
await RNFetchBlob.fs.unlink(cacheDir + `/${file}`).catch(console.log); await RNFetchBlob.fs.unlink(cacheDir + `/${file}`).catch(() => {
/* empty */
});
} }
for (const file of oldCache) { for (const file of oldCache) {
await RNFetchBlob.fs.unlink(cacheDirOld + `/${file}`).catch(console.log); await RNFetchBlob.fs.unlink(cacheDirOld + `/${file}`).catch(() => {
/* empty */
});
} }
} catch (e) { } catch (e) {
DatabaseLogger.error(e, "clearFileStorage"); DatabaseLogger.error(e, "clearFileStorage");
@@ -161,20 +172,19 @@ export async function migrateFilesFromCache() {
const migratedFilesPath = cacheDir + "/.migrated_1"; const migratedFilesPath = cacheDir + "/.migrated_1";
const migrated = await RNFetchBlob.fs.exists(migratedFilesPath); const migrated = await RNFetchBlob.fs.exists(migratedFilesPath);
if (migrated) { if (migrated) {
console.log("Files migrated already");
return; return;
} }
const files = await RNFetchBlob.fs.ls(cacheDir); const files = await RNFetchBlob.fs.ls(cacheDir);
console.log("Files to migrate:", files.join(","));
const oldCache = await RNFetchBlob.fs.ls(cacheDirOld); const oldCache = await RNFetchBlob.fs.ls(cacheDirOld);
for (const file of oldCache) { for (const file of oldCache) {
if (file.startsWith("org.") || file.startsWith("com.")) continue; if (file.startsWith("org.") || file.startsWith("com.")) continue;
RNFetchBlob.fs RNFetchBlob.fs
.mv(cacheDirOld + `/${file}`, cacheDir + `/${file}`) .mv(cacheDirOld + `/${file}`, cacheDir + `/${file}`)
.catch(console.log); .catch(() => {
console.log("Moved", file); /* empty */
});
} }
await RNFetchBlob.fs.createFile(migratedFilesPath, "1", "utf8"); await RNFetchBlob.fs.createFile(migratedFilesPath, "1", "utf8");
} catch (e) { } catch (e) {
@@ -183,13 +193,17 @@ export async function migrateFilesFromCache() {
} }
export async function clearCache() { export async function clearCache() {
await RNFetchBlob.fs.unlink(cacheDir).catch(console.log); await RNFetchBlob.fs.unlink(cacheDir).catch(() => {
/* empty */
});
await createCacheDir(); await createCacheDir();
eSendEvent("cache-cleared"); eSendEvent("cache-cleared");
} }
export async function deleteCacheFileByPath(path: string) { export async function deleteCacheFileByPath(path: string) {
await RNFetchBlob.fs.unlink(path).catch(console.log); await RNFetchBlob.fs.unlink(path).catch(() => {
/* empty */
});
} }
export async function deleteCacheFileByName(name: string) { export async function deleteCacheFileByName(name: string) {
@@ -198,15 +212,21 @@ export async function deleteCacheFileByName(name: string) {
? await (RNFetchBlob.fs as any).pathForAppGroup(IOS_APPGROUPID) ? await (RNFetchBlob.fs as any).pathForAppGroup(IOS_APPGROUPID)
: null; : null;
const appGroupPath = `${iosAppGroup}/${name}`; const appGroupPath = `${iosAppGroup}/${name}`;
await RNFetchBlob.fs.unlink(appGroupPath).catch(console.log); await RNFetchBlob.fs.unlink(appGroupPath).catch(() => {
await RNFetchBlob.fs.unlink(`${cacheDir}/${name}`).catch(console.log); /* empty */
});
await RNFetchBlob.fs.unlink(`${cacheDir}/${name}`).catch(() => {
/* empty */
});
} }
export async function deleteDCacheFiles() { export async function deleteDCacheFiles() {
const files = await RNFetchBlob.fs.ls(cacheDir); const files = await RNFetchBlob.fs.ls(cacheDir);
for (const file of files) { for (const file of files) {
if (file.includes("_dcache") || file.startsWith("NN_")) { if (file.includes("_dcache") || file.startsWith("NN_")) {
await RNFetchBlob.fs.unlink(file).catch(console.log); await RNFetchBlob.fs.unlink(file).catch(() => {
/* empty */
});
} }
} }
} }
@@ -245,7 +265,9 @@ export async function exists(filename: string) {
); );
RNFetchBlob.fs RNFetchBlob.fs
.unlink(existsInAppGroup ? appGroupPath : path) .unlink(existsInAppGroup ? appGroupPath : path)
.catch(console.log); .catch(() => {
/* empty */
});
return false; return false;
} }
@@ -281,7 +303,7 @@ export async function getCacheSize() {
await createCacheDir(); await createCacheDir();
const stat = await RNFetchBlob.fs.lstat(`file://` + cacheDir); const stat = await RNFetchBlob.fs.lstat(`file://` + cacheDir);
let total = 0; let total = 0;
console.log("Total files", stat.length);
stat.forEach((file) => { stat.forEach((file) => {
total += parseInt(file.size as unknown as string); total += parseInt(file.size as unknown as string);
}); });

View File

@@ -17,9 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
function info(context: string, ...logs: unknown[]) { function info(context: string, ...logs: unknown[]) {}
console.log(`${new Date().toLocaleDateString()}::info::${context}:`, ...logs);
}
function error(context: string, ...logs: unknown[]) { function error(context: string, ...logs: unknown[]) {
console.log( console.log(

View File

@@ -41,7 +41,9 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
await sleep(500); await sleep(500);
} }
if (item.type === "link") { if (item.type === "link") {
Linking.openURL(item.data).catch(console.log); Linking.openURL(item.data).catch(() => {
/* empty */
});
} else if (item.type === "promo") { } else if (item.type === "promo") {
presentSheet({ presentSheet({
component: ( component: (

View File

@@ -528,7 +528,9 @@ export const AttachmentDialog = ({
setAttachments(results); setAttachments(results);
setLoading(false); setLoading(false);
}) })
.catch(console.log); .catch(() => {
/* empty */
});
}} }}
/> />
) )

View File

@@ -88,7 +88,6 @@ export const ChangePassword = () => {
await sleep(300); await sleep(300);
eSendEvent(eOpenRecoveryKeyDialog); eSendEvent(eOpenRecoveryKeyDialog);
} catch (e) { } catch (e) {
console.log(e.stack);
setLoading(false); setLoading(false);
ToastManager.show({ ToastManager.show({
heading: strings.passwordChangeFailed(), heading: strings.passwordChangeFailed(),

View File

@@ -70,7 +70,7 @@ export const useLogin = (onFinishLogin, sessionExpired = false) => {
switch (step) { switch (step) {
case LoginSteps.emailAuth: { case LoginSteps.emailAuth: {
const mfaInfo = await db.user.authenticateEmail(email.current); const mfaInfo = await db.user.authenticateEmail(email.current);
console.log("email auth", mfaInfo);
if (mfaInfo) { if (mfaInfo) {
TwoFactorVerification.present( TwoFactorVerification.present(
async (mfa, callback) => { async (mfa, callback) => {

View File

@@ -180,7 +180,7 @@ AttachImage.present = (response: ImageType[], context?: string) => {
close={close} close={close}
onAttach={(result) => { onAttach={(result) => {
resolved = true; resolved = true;
console.log("closing");
resolve(result); resolve(result);
close?.(); close?.();
}} }}

View File

@@ -307,9 +307,7 @@ const PDFPreview = () => {
password={password} password={password}
maxScale={6} maxScale={6}
onError={onError} onError={onError}
onPressLink={(uri) => { onPressLink={(uri) => {}}
console.log(`Link pressed: ${uri}`);
}}
style={{ style={{
flex: 1, flex: 1,
width: width, width: width,

View File

@@ -62,7 +62,7 @@ export default function Progress() {
eSubscribeEvent(PROGRESS_EVENTS.start, (options: ProgressOptions) => { eSubscribeEvent(PROGRESS_EVENTS.start, (options: ProgressOptions) => {
setProgress(options.progress); setProgress(options.progress);
cancelCallback.current = options.cancelCallback; cancelCallback.current = options.cancelCallback;
console.log("options", options.fillBackground);
setData({ setData({
title: options.title, title: options.title,
paragraph: options.paragraph, paragraph: options.paragraph,

View File

@@ -336,7 +336,7 @@ export class VaultDialog extends Component {
); );
}); });
} }
console.log("VAULT UPDATED EVENT");
eSendEvent("vaultUpdated"); eSendEvent("vaultUpdated");
this.setState({ this.setState({
loading: false loading: false
@@ -406,7 +406,6 @@ export class VaultDialog extends Component {
} else { } else {
await db.vault.add(this.state.note.id); await db.vault.add(this.state.note.id);
console.log("update note event...");
eSendEvent(eUpdateNoteInEditor, this.state.note, true); eSendEvent(eUpdateNoteInEditor, this.state.note, true);
this.close(); this.close();
@@ -543,7 +542,6 @@ export class VaultDialog extends Component {
this.close(); this.close();
}) })
.catch((e) => { .catch((e) => {
console.log("Error", e);
this._takeErrorAction(e); this._takeErrorAction(e);
}); });
} }

View File

@@ -78,10 +78,10 @@ class ExceptionHandler extends React.Component<{
} }
export const withErrorBoundry = (Element: React.ElementType, name: string) => { export const withErrorBoundry = (Element: React.ElementType, name: string) => {
return function ErrorBoundary() { return function ErrorBoundary(props: any) {
return ( return (
<ExceptionHandler component={name}> <ExceptionHandler component={name}>
<Element /> <Element {...props} />
</ExceptionHandler> </ExceptionHandler>
); );
}; };

View File

@@ -54,7 +54,7 @@ export const Header = ({
onSearch onSearch
}: { }: {
onLeftMenuButtonPress?: () => void; onLeftMenuButtonPress?: () => void;
renderedInRoute: RouteName; renderedInRoute?: RouteName;
id?: string; id?: string;
title: string; title: string;
headerRightButtons?: HeaderRightButton[]; headerRightButtons?: HeaderRightButton[];

View File

@@ -41,7 +41,7 @@ export const RightMenus = ({
onSearch onSearch
}: { }: {
headerRightButtons?: HeaderRightButton[]; headerRightButtons?: HeaderRightButton[];
renderedInRoute: RouteName; renderedInRoute?: RouteName;
id?: string; id?: string;
onPressDefaultRightButton?: () => void; onPressDefaultRightButton?: () => void;
search?: boolean; search?: boolean;

View File

@@ -41,7 +41,7 @@ export const Title = ({
isHiddenOnRender?: boolean; isHiddenOnRender?: boolean;
accentColor?: string; accentColor?: string;
isBeta?: boolean; isBeta?: boolean;
renderedInRoute: string; renderedInRoute?: string;
id?: string; id?: string;
}) => { }) => {
const { colors } = useThemeColors(); const { colors } = useThemeColors();

View File

@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import Sodium from "@ammarahmed/react-native-sodium"; import Sodium from "@ammarahmed/react-native-sodium";
import { DataURL } from "@notesnook/core"; import { DataURL, getFileNameWithExtension } from "@notesnook/core";
import type { ImageAttributes } from "@notesnook/editor"; import type { ImageAttributes } from "@notesnook/editor";
import { useThemeColors } from "@notesnook/theme"; import { useThemeColors } from "@notesnook/theme";
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
@@ -86,8 +86,12 @@ const ImagePreview = () => {
return; return;
} }
const attachment = await db.attachments.attachment(hash); const attachment = await db.attachments.attachment(hash);
const path = `${cacheDir}/${"NN_" + attachment?.filename}`; const path = `${cacheDir}/${
await RNFetchBlob.fs.mv(`${cacheDir}/${uri}`, path).catch(console.log); "NN_" + (await getFileNameWithExtension(hash, attachment?.mimeType))
}`;
await RNFetchBlob.fs.mv(`${cacheDir}/${uri}`, path).catch(() => {
/* empty */
});
setImage("file://" + path); setImage("file://" + path);
setLoading(false); setLoading(false);
}, 100); }, 100);
@@ -95,11 +99,15 @@ const ImagePreview = () => {
const close = React.useCallback(() => { const close = React.useCallback(() => {
image && image &&
RNFetchBlob.fs.unlink(image.replace("file://", "")).catch(console.log); RNFetchBlob.fs.unlink(image.replace("file://", "")).catch(() => {
/* empty */
});
setImage(undefined); setImage(undefined);
setVisible(false); setVisible(false);
}, [image]); }, [image]);
console.log("image", image);
const renderHeader = React.useCallback( const renderHeader = React.useCallback(
() => ( () => (
<View <View
@@ -125,13 +133,18 @@ const ImagePreview = () => {
<IconButton <IconButton
name="share" name="share"
color="white" color="white"
style={{
borderWidth: 0
}}
onPress={async () => { onPress={async () => {
useSettingStore useSettingStore
.getState() .getState()
.setAppDidEnterBackgroundForAction(true); .setAppDidEnterBackgroundForAction(true);
await Share.open({ await Share.open({
url: image url: image
}).catch(console.log); }).catch(() => {
/* empty */
});
useSettingStore useSettingStore
.getState() .getState()
.setAppDidEnterBackgroundForAction(false); .setAppDidEnterBackgroundForAction(false);
@@ -147,7 +160,7 @@ const ImagePreview = () => {
</View> </View>
</View> </View>
), ),
[close, image, showHeader] [close, image, insets.top, showHeader]
); );
return ( return (

View File

@@ -153,9 +153,7 @@ export function ListItemWrapper(props: ListItemWrapperProps) {
}, },
items?.cacheItem(index) ? 100 : 0 items?.cacheItem(index) ? 100 : 0
); );
} catch (e) { } catch (e) {}
console.log("Error", e);
}
})(); })();
}, [index, items, refreshItem]); }, [index, items, refreshItem]);

View File

@@ -119,7 +119,6 @@ export const PricingPlans = ({
setLoading(false); setLoading(false);
} catch (e) { } catch (e) {
setLoading(false); setLoading(false);
console.log("error getting sku", e);
} }
}, [promo?.promoCode]); }, [promo?.promoCode]);
@@ -171,7 +170,6 @@ export const PricingPlans = ({
}); });
return true; return true;
} catch (e) { } catch (e) {
console.log("PROMOCODE ERROR:", code, e);
return false; return false;
} }
}; };
@@ -231,7 +229,6 @@ export const PricingPlans = ({
}); });
} catch (e) { } catch (e) {
setBuying(false); setBuying(false);
console.log(e);
} }
}; };

View File

@@ -100,7 +100,6 @@ export const AddNotebookSheet = ({
eSendEvent(eOnNotebookUpdated, parent); eSendEvent(eOnNotebookUpdated, parent);
if (notebook) { if (notebook) {
setImmediate(() => { setImmediate(() => {
console.log(parent, notebook.id);
eSendEvent(eOnNotebookUpdated, notebook.id); eSendEvent(eOnNotebookUpdated, notebook.id);
}); });
} }

View File

@@ -90,13 +90,12 @@ export const NotebookItem = ({
for (const key in keys) { for (const key in keys) {
nextState[key] = !state.initialState[key] ? undefined : "deselected"; nextState[key] = !state.initialState[key] ? undefined : "deselected";
} }
console.log("Single item selection");
state.setSelection({ state.setSelection({
[item.id]: "selected", [item.id]: "selected",
...nextState ...nextState
}); });
} else { } else {
console.log("Multi item selection");
state.markAs(item, "selected"); state.markAs(item, "selected");
} }
}; };

View File

@@ -333,13 +333,17 @@ const ExportNotesSheet = ({
if (Platform.OS === "ios") { if (Platform.OS === "ios") {
Share.open({ Share.open({
url: result?.fileDir + result.fileName url: result?.fileDir + result.fileName
}).catch(console.log); }).catch(() => {
/* empty */
});
} else { } else {
FileViewer.open(result.filePath, { FileViewer.open(result.filePath, {
showOpenWithDialog: true, showOpenWithDialog: true,
showAppsSuggestions: true, showAppsSuggestions: true,
shareFile: true shareFile: true
} as any).catch(console.log); } as any).catch(() => {
/* empty */
});
} }
}} }}
/> />

View File

@@ -62,7 +62,9 @@ export const ShareComponent = ({ uri, name, padding }) => {
showOpenWithDialog: true, showOpenWithDialog: true,
showAppsSuggestions: true, showAppsSuggestions: true,
shareFile: true shareFile: true
}).catch(console.log); }).catch(() => {
/* empty */
});
}} }}
/> />
</View> </View>

View File

@@ -113,11 +113,9 @@ const ManageTagsSheet = (props: {
.sorted() .sorted()
.then((items) => { .then((items) => {
setTags(items); setTags(items);
console.log("searched tags");
}); });
} else { } else {
db.tags.all.sorted(db.settings.getGroupOptions("tags")).then((items) => { db.tags.all.sorted(db.settings.getGroupOptions("tags")).then((items) => {
console.log("items loaded tags", items.placeholders.length);
setTags(items); setTags(items);
}); });
} }

View File

@@ -191,13 +191,17 @@ class RecoveryKeySheet extends React.Component {
Share.open({ Share.open({
url: path, url: path,
failOnCancel: false failOnCancel: false
}).catch(console.log); }).catch(() => {
/* empty */
});
} else { } else {
FileViewer.open(path, { FileViewer.open(path, {
showOpenWithDialog: true, showOpenWithDialog: true,
showAppsSuggestions: true, showAppsSuggestions: true,
shareFile: true shareFile: true
}).catch(console.log); }).catch(() => {
/* empty */
});
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);

View File

@@ -273,7 +273,7 @@ const ListNoteItem = ({
listType, listType,
noteInternalLinks.length noteInternalLinks.length
]); ]);
console.log(noteInternalLinks);
const renderBlock = React.useCallback( const renderBlock = React.useCallback(
(block: ContentBlock) => ( (block: ContentBlock) => (
<ListBlockItem <ListBlockItem
@@ -419,7 +419,6 @@ export const ReferencesList = ({ item, close }: ReferencesListProps) => {
id={index} id={index}
items={items} items={items}
onSelect={(note, blockId) => { onSelect={(note, blockId) => {
console.log(note.id, blockId);
eSendEvent(eOnLoadNote, { eSendEvent(eOnLoadNote, {
item: note, item: note,
blockId: blockId blockId: blockId

View File

@@ -38,7 +38,7 @@ const Sort = ({ type, screen }) => {
); );
const updateGroupOptions = async (_groupOptions) => { const updateGroupOptions = async (_groupOptions) => {
const groupType = screen === "Notes" ? "home" : type + "s"; const groupType = screen === "Notes" ? "home" : type + "s";
console.log("updateGroupOptions for group", groupType, "in", screen);
await db.settings.setGroupOptions(groupType, _groupOptions); await db.settings.setGroupOptions(groupType, _groupOptions);
setGroupOptions(_groupOptions); setGroupOptions(_groupOptions);
setTimeout(() => { setTimeout(() => {

View File

@@ -215,7 +215,9 @@ export const Update = ({ version: appVersion, fwdRef }) => {
marginTop: 10 marginTop: 10
}} }}
onPress={() => { onPress={() => {
Linking.openURL(GITHUB_PAGE_URL).catch(console.log); Linking.openURL(GITHUB_PAGE_URL).catch(() => {
/* empty */
});
}} }}
> >
{strings.readReleaseNotes()} {strings.readReleaseNotes()}

View File

@@ -315,7 +315,9 @@ const trialstarted: { id: string; steps: TStep[] } = {
actionButton: { actionButton: {
text: strings.joinDiscord(), text: strings.joinDiscord(),
action: () => { action: () => {
Linking.openURL("https://discord.gg/zQBK97EE22").catch(console.log); Linking.openURL("https://discord.gg/zQBK97EE22").catch(() => {
/* empty */
});
} }
} }
} }
@@ -366,7 +368,9 @@ const Support = () => {
width: "90%" width: "90%"
}} }}
onPress={() => { onPress={() => {
Linking.openURL("https://discord.gg/zQBK97EE22").catch(console.log); Linking.openURL("https://discord.gg/zQBK97EE22").catch(() => {
/* empty */
});
}} }}
icon="discord" icon="discord"
type="secondary" type="secondary"
@@ -380,7 +384,9 @@ const Support = () => {
width: "90%" width: "90%"
}} }}
onPress={() => { onPress={() => {
Linking.openURL("https://t.me/notesnook").catch(console.log); Linking.openURL("https://t.me/notesnook").catch(() => {
/* empty */
});
}} }}
icon="telegram" icon="telegram"
type="secondary" type="secondary"

View File

@@ -66,6 +66,7 @@ import {
eSubscribeEvent, eSubscribeEvent,
presentSheet presentSheet
} from "../services/event-manager"; } from "../services/event-manager";
import { IntentService } from "../services/intent";
import { import {
clearMessage, clearMessage,
setEmailVerifyMessage, setEmailVerifyMessage,
@@ -148,7 +149,6 @@ const onUploadedAttachmentProgress = (data: any) => {
}; };
const onUserSessionExpired = async () => { const onUserSessionExpired = async () => {
console.log("LOGGED OUT USER....");
SettingsService.set({ SettingsService.set({
sessionExpired: true sessionExpired: true
}); });
@@ -254,9 +254,7 @@ async function checkForShareExtensionLaunchedInBackground() {
if (note) setTimeout(() => eSendEvent("loadingNote", note), 1); if (note) setTimeout(() => eSendEvent("loadingNote", note), 1);
MMKV.removeItem("shareExtensionOpened"); MMKV.removeItem("shareExtensionOpened");
} }
} catch (e) { } catch (e) {}
console.log(e);
}
} }
async function saveEditorState() { async function saveEditorState() {
@@ -502,7 +500,9 @@ export const useAppEvents = () => {
} }
if (SettingsService.getProperty("offlineMode")) { if (SettingsService.getProperty("offlineMode")) {
db.attachments.cacheAttachments().catch(console.log); db.attachments.cacheAttachments().catch(() => {
/* empty */
});
} }
} }
}, []); }, []);
@@ -550,7 +550,6 @@ export const useAppEvents = () => {
}); });
} }
} catch (e) { } catch (e) {
console.log(e);
ToastManager.error(e as Error, "Error updating user", "global"); ToastManager.error(e as Error, "Error updating user", "global");
} }
@@ -645,6 +644,7 @@ export const useAppEvents = () => {
const emitterSubscriptions = [ const emitterSubscriptions = [
Linking.addEventListener("url", onAppOpenedFromURL), Linking.addEventListener("url", onAppOpenedFromURL),
SodiumEventEmitter.addListener( SodiumEventEmitter.addListener(
"onSodiumProgress", "onSodiumProgress",
onFileEncryptionProgress onFileEncryptionProgress
@@ -695,6 +695,10 @@ export const useAppEvents = () => {
// Reset the editor if the app has been in background for more than 10 minutes. // Reset the editor if the app has been in background for more than 10 minutes.
eSendEvent(eEditorReset); eSendEvent(eEditorReset);
} }
setTimeout(async () => {
IntentService.onAppStateChanged();
}, 100);
} else { } else {
await saveEditorState(); await saveEditorState();
if ( if (
@@ -779,9 +783,7 @@ export const useAppEvents = () => {
useEffect(() => { useEffect(() => {
if (!appLocked && isAppLoading) { if (!appLocked && isAppLoading) {
initializeLogger() initializeLogger()
.catch((e) => { .catch((e) => {})
console.log(e);
})
.finally(() => { .finally(() => {
//@ts-ignore //@ts-ignore
initializeDatabase(); initializeDatabase();

View File

@@ -196,7 +196,6 @@ export const useTotalNotes = (type: "notebook" | "tag" | "color") => {
} }
setTotalNotesById(totalNotesById); setTotalNotesById(totalNotesById);
}); });
console.log("useTotalNotes.getTotalNotes");
}, },
[type] [type]
); );

View File

@@ -31,7 +31,7 @@ export function useGroupOptions(type: any) {
const onUpdate = (groupType: string) => { const onUpdate = (groupType: string) => {
if (groupType !== type) return; if (groupType !== type) return;
const options = db.settings?.getGroupOptions(type) as any; const options = db.settings?.getGroupOptions(type) as any;
console.log("useGroupOptions.onUpdate", type, options);
if ( if (
groupOptions?.groupBy !== options.groupBy || groupOptions?.groupBy !== options.groupBy ||
groupOptions?.sortBy !== options.sortBy || groupOptions?.sortBy !== options.sortBy ||

View File

@@ -74,10 +74,8 @@ export const useNotebook = (
}; };
const onUpdate = (type: string) => { const onUpdate = (type: string) => {
console.log("event", type);
if (type !== "notebooks") return; if (type !== "notebooks") return;
onRequestUpdate(); onRequestUpdate();
console.log("useNotebook.onUpdate", item?.id, Date.now());
}; };
eSubscribeEvent(eGroupOptionsUpdated, onUpdate); eSubscribeEvent(eGroupOptionsUpdated, onUpdate);

View File

@@ -45,6 +45,9 @@ import { useSelectionStore } from "../stores/use-selection-store";
import { useSettingStore } from "../stores/use-setting-store"; import { useSettingStore } from "../stores/use-setting-store";
import { rootNavigatorRef } from "../utils/global-refs"; import { rootNavigatorRef } from "../utils/global-refs";
import { strings } from "@notesnook/intl"; import { strings } from "@notesnook/intl";
import { IntentService } from "../services/intent";
import ReminderSheet from "../components/sheets/reminder";
import { db } from "../common/database";
const NativeStack = createNativeStackNavigator(); const NativeStack = createNativeStackNavigator();
const IntroStack = createNativeStackNavigator(); const IntroStack = createNativeStackNavigator();
@@ -76,12 +79,24 @@ const _Tabs = () => {
const introCompleted = useSettingStore( const introCompleted = useSettingStore(
(state) => state.settings.introCompleted (state) => state.settings.introCompleted
); );
const height = useSettingStore((state) => state.dimensions.height); const height = useSettingStore((state) => state.dimensions.height);
const insets = useGlobalSafeAreaInsets(); const insets = useGlobalSafeAreaInsets();
const screenHeight = height - (50 + insets.top + insets.bottom); const screenHeight = height - (50 + insets.top + insets.bottom);
React.useEffect(() => { React.useEffect(() => {
setTimeout(() => { setTimeout(async () => {
useNavigationStore.getState().update(homepage); useNavigationStore.getState().update(homepage);
const intent = IntentService.getLaunchIntent();
if (intent && intent["com.streetwriters.notesnook.OpenReminderId"]) {
const reminder = await db.reminders.reminder(
intent["com.streetwriters.notesnook.OpenReminderId"]
);
if (reminder) {
ReminderSheet.present(reminder);
}
} else if (intent["com.streetwriters.notesnook.NewReminder"]) {
ReminderSheet.present();
}
}, 1000); }, 1000);
}, [homepage]); }, [homepage]);

View File

@@ -229,7 +229,7 @@ const useLockedNoteHandler = () => {
const unlockWithBiometrics = async () => { const unlockWithBiometrics = async () => {
try { try {
if (!tabRef.current?.noteLocked || !tabRef.current) return; if (!tabRef.current?.noteLocked || !tabRef.current) return;
console.log("Trying to unlock with biometrics...");
const credentials = await BiometricService.getCredentials( const credentials = await BiometricService.getCredentials(
"Unlock note", "Unlock note",
"Unlock note to open it in editor." "Unlock note to open it in editor."
@@ -305,7 +305,6 @@ const useLockedNoteHandler = () => {
locked: false locked: false
}); });
} catch (e) { } catch (e) {
console.log(e);
ToastManager.show({ ToastManager.show({
heading: strings.passwordIncorrect(), heading: strings.passwordIncorrect(),
type: "error" type: "error"
@@ -324,7 +323,6 @@ const useLockedNoteHandler = () => {
unlockWithBiometrics(); unlockWithBiometrics();
}, 150); }, 150);
} else { } else {
console.log("Biometrics unavailable.", editorState().movedAway);
if (!editorState().movedAway) { if (!editorState().movedAway) {
setTimeout(() => { setTimeout(() => {
if (tabRef.current && tabRef.current?.locked) { if (tabRef.current && tabRef.current?.locked) {

View File

@@ -74,7 +74,6 @@ export function ReadonlyEditor(props: {
} }
if (editorMessage.type === EventTypes.readonlyEditorLoaded) { if (editorMessage.type === EventTypes.readonlyEditorLoaded) {
console.log("Readonly editor loaded.");
props.onLoad?.((content: { data: string; id: string }) => { props.onLoad?.((content: { data: string; id: string }) => {
setTimeout(() => { setTimeout(() => {
noteId.current = content.id; noteId.current = content.id;
@@ -90,7 +89,6 @@ export function ReadonlyEditor(props: {
} else if (editorMessage.type === EventTypes.getAttachmentData) { } else if (editorMessage.type === EventTypes.getAttachmentData) {
const attachment = (editorMessage.value as any).attachment as Attachment; const attachment = (editorMessage.value as any).attachment as Attachment;
console.log("Getting attachment data:", attachment.hash, attachment.type);
downloadAttachment(attachment.hash, true, { downloadAttachment(attachment.hash, true, {
base64: attachment.type === "image", base64: attachment.type === "image",
text: attachment.type === "web-clip", text: attachment.type === "web-clip",
@@ -115,7 +113,6 @@ export function ReadonlyEditor(props: {
); );
}) })
.catch(() => { .catch(() => {
console.log("Error downloading attachment data");
editorRef.current?.postMessage( editorRef.current?.postMessage(
JSON.stringify({ JSON.stringify({
type: EditorEvents.attachmentData, type: EditorEvents.attachmentData,

View File

@@ -196,9 +196,7 @@ const camera = async (options: PickerOptions) => {
options options
); );
}) })
.catch((e) => { .catch((e) => {});
console.log("camera error: ", e);
});
} catch (e) { } catch (e) {
ToastManager.show({ ToastManager.show({
heading: (e as Error).message, heading: (e as Error).message,
@@ -226,9 +224,7 @@ const gallery = async (options: PickerOptions) => {
options options
) )
) )
.catch((e) => { .catch((e) => {});
console.log("gallery error: ", e);
});
} catch (e) { } catch (e) {
useSettingStore.getState().setAppDidEnterBackgroundForAction(false); useSettingStore.getState().setAppDidEnterBackgroundForAction(false);
ToastManager.show({ ToastManager.show({
@@ -236,7 +232,6 @@ const gallery = async (options: PickerOptions) => {
type: "error", type: "error",
context: "global" context: "global"
}); });
console.log("attachment error:", e);
} }
}; };
@@ -321,18 +316,14 @@ const handleImageResponse = async (
? fileName.replace(/HEIC|HEIF/, "jpeg") ? fileName.replace(/HEIC|HEIF/, "jpeg")
: fileName; : fileName;
console.log("attaching image...", fileName);
console.log("attaching file...");
if (!(await attachFile(uri, hash, image.mime, fileName, options))) return; if (!(await attachFile(uri, hash, image.mime, fileName, options))) return;
if (Platform.OS === "ios") await RNFetchBlob.fs.unlink(uri); if (Platform.OS === "ios") await RNFetchBlob.fs.unlink(uri);
console.log("attaching image to note...");
if ( if (
options.tabId !== undefined && options.tabId !== undefined &&
useTabStore.getState().getNoteIdForTab(options.tabId) === options.noteId useTabStore.getState().getNoteIdForTab(options.tabId) === options.noteId
) { ) {
console.log("attaching image to note...");
editorController.current?.commands.insertImage( editorController.current?.commands.insertImage(
{ {
hash: hash, hash: hash,
@@ -407,7 +398,7 @@ export async function attachFile(
} else { } else {
encryptionInfo = { hash: hash }; encryptionInfo = { hash: hash };
} }
console.log("FILE ENCRYPTED....", encryptionInfo);
await db.attachments.add(encryptionInfo); await db.attachments.add(encryptionInfo);
return true; return true;
} catch (e) { } catch (e) {

View File

@@ -94,4 +94,5 @@ export type AppState = {
editing: boolean; editing: boolean;
movedAway: boolean; movedAway: boolean;
timestamp: number; timestamp: number;
noteId?: string;
}; };

View File

@@ -268,7 +268,6 @@ export const useEditorEvents = (
}, [editor, deviceMode, fullscreen]); }, [editor, deviceMode, fullscreen]);
const onHardwareBackPress = useCallback(() => { const onHardwareBackPress = useCallback(() => {
console.log(tabBarRef.current?.page());
if (tabBarRef.current?.page() === 2) { if (tabBarRef.current?.page() === 2) {
onBackPress(); onBackPress();
return true; return true;
@@ -574,7 +573,7 @@ export const useEditorEvents = (
// tabs: (editorMessage.value as any)?.tabs, // tabs: (editorMessage.value as any)?.tabs,
// currentTab: (editorMessage.value as any)?.currentTab // currentTab: (editorMessage.value as any)?.currentTab
// }); // });
// console.log("Tabs updated"); //
break; break;
} }
case EventTypes.toc: case EventTypes.toc:
@@ -597,14 +596,6 @@ export const useEditorEvents = (
break; break;
} }
case EventTypes.tabFocused: { case EventTypes.tabFocused: {
console.log(
"Focused tab",
editorMessage.tabId,
editorMessage.noteId,
"Content:",
editorMessage.value
);
eSendEvent(eEditorTabFocused, editorMessage.tabId); eSendEvent(eEditorTabFocused, editorMessage.tabId);
if ( if (

View File

@@ -46,6 +46,7 @@ import {
eUnSubscribeEvent eUnSubscribeEvent
} from "../../../services/event-manager"; } from "../../../services/event-manager";
import Navigation from "../../../services/navigation"; import Navigation from "../../../services/navigation";
import { NotePreviewWidget } from "../../../services/note-preview-widget";
import Notifications from "../../../services/notifications"; import Notifications from "../../../services/notifications";
import SettingsService from "../../../services/settings"; import SettingsService from "../../../services/settings";
import { useSettingStore } from "../../../stores/use-setting-store"; import { useSettingStore } from "../../../stores/use-setting-store";
@@ -152,7 +153,6 @@ export const useEditor = (
useEffect(() => { useEffect(() => {
const event = eSubscribeEvent(eEditorTabFocused, (tabId) => { const event = eSubscribeEvent(eEditorTabFocused, (tabId) => {
console.log("Editot tab focus changed", lastTabFocused.current, tabId);
if (lastTabFocused.current !== tabId) lock.current = false; if (lastTabFocused.current !== tabId) lock.current = false;
lastTabFocused.current = tabId as number; lastTabFocused.current = tabId as number;
}); });
@@ -189,7 +189,6 @@ export const useEditor = (
const reset = useCallback( const reset = useCallback(
async (tabId: number, resetState = true, resetContent = true) => { async (tabId: number, resetState = true, resetContent = true) => {
console.log("Resetting tab:", tabId);
const noteId = useTabStore.getState().getNoteIdForTab(tabId); const noteId = useTabStore.getState().getNoteIdForTab(tabId);
if (noteId) { if (noteId) {
currentNotes.current?.id && db.fs().cancel(noteId); currentNotes.current?.id && db.fs().cancel(noteId);
@@ -392,6 +391,13 @@ export const useEditor = (
} }
saveCount.current++; saveCount.current++;
clearTimeout(timers.current.onsave);
timers.current.onsave = setTimeout(async () => {
if (!id || !note) return;
NotePreviewWidget.updateNote(id, note);
}, 500);
return id; return id;
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@@ -438,7 +444,6 @@ export const useEditor = (
presistTab?: boolean; presistTab?: boolean;
}) => { }) => {
if (!event) return; if (!event) return;
console.log(event.item?.id, event?.item?.title, "loading note...");
if (event.blockId) { if (event.blockId) {
blockIdRef.current = event.blockId; blockIdRef.current = event.blockId;
@@ -469,7 +474,7 @@ export const useEditor = (
overlay(false); overlay(false);
return; return;
} }
console.log("LOADING NOTE", event.item.id);
const item = event.item; const item = event.item;
const currentTab = useTabStore const currentTab = useTabStore
@@ -502,7 +507,6 @@ export const useEditor = (
} }
}, 150); }, 150);
} }
console.log("Note already loaded, focusing the tab");
} else { } else {
if (event.presistTab) { if (event.presistTab) {
// Open note in new tab. // Open note in new tab.
@@ -513,9 +517,7 @@ export const useEditor = (
noteId: event.item.id, noteId: event.item.id,
previewTab: false previewTab: false
}); });
console.log("Opening note in new tab");
} else { } else {
console.log("Opening note in preview tab");
// Otherwise we focus the preview tab or create one to open the note in. // Otherwise we focus the preview tab or create one to open the note in.
useTabStore.getState().focusPreviewTab(event.item.id, { useTabStore.getState().focusPreviewTab(event.item.id, {
readonly: event.item.readonly || readonly, readonly: event.item.readonly || readonly,
@@ -533,11 +535,11 @@ export const useEditor = (
const tabId = event.tabId || useTabStore.getState().currentTab; const tabId = event.tabId || useTabStore.getState().currentTab;
if (lastTabFocused.current !== tabId) { if (lastTabFocused.current !== tabId) {
// if ((await waitForEvent(eEditorTabFocused, 1000)) !== tabId) { // if ((await waitForEvent(eEditorTabFocused, 1000)) !== tabId) {
// console.log("tab id did not match after focus in 1000ms"); //
// return; // return;
// } // }
currentLoadingNoteId.current = item.id; currentLoadingNoteId.current = item.id;
console.log("Waiting for tab to focus");
return; return;
} }
@@ -555,7 +557,7 @@ export const useEditor = (
loadingState.current === currentContents.current[item.id]?.data loadingState.current === currentContents.current[item.id]?.data
) { ) {
// If note is already loading, return. // If note is already loading, return.
console.log("Note is already loading...");
return; return;
} }
@@ -632,7 +634,6 @@ export const useEditor = (
if (isDeleted(data) || isTrashItem(data)) { if (isDeleted(data) || isTrashItem(data)) {
const tabId = useTabStore.getState().getTabForNote(data.id); const tabId = useTabStore.getState().getTabForNote(data.id);
if (tabId !== undefined) { if (tabId !== undefined) {
console.log("Removing tab");
await commands.clearContent(tabId); await commands.clearContent(tabId);
useTabStore.getState().removeTab(tabId); useTabStore.getState().removeTab(tabId);
} }
@@ -915,24 +916,34 @@ export const useEditor = (
state.current.ready = true; state.current.ready = true;
} }
const noteId = useTabStore.getState().getCurrentNoteId(); const appState = getAppState();
if (!noteId) { if (appState?.noteId) {
loadNote({ newNote: true }); const note = await db.notes?.note(appState.noteId);
if (tabBarRef.current?.page() === 1) {
state.current.currentlyEditing = false;
}
} else if (state.current?.initialLoadCalled) {
const note = currentNotes.current[noteId];
if (note) { if (note) {
loadNote({ loadNote({
item: note item: note
}); });
} }
} else {
const noteId = useTabStore.getState().getCurrentNoteId();
if (!noteId) {
loadNote({ newNote: true });
if (tabBarRef.current?.page() === 1) {
state.current.currentlyEditing = false;
}
} else if (state.current?.initialLoadCalled) {
const note = currentNotes.current[noteId];
if (note) {
loadNote({
item: note
});
}
}
if (!state.current?.initialLoadCalled) {
state.current.initialLoadCalled = true;
}
overlay(false);
} }
if (!state.current?.initialLoadCalled) {
state.current.initialLoadCalled = true;
}
overlay(false);
}, [ }, [
postMessage, postMessage,
theme, theme,

View File

@@ -167,7 +167,7 @@ export const useTabStore = create<TabStore>(
previewTab: true, previewTab: true,
noteId: noteId noteId: noteId
}; };
console.log("focus preview", noteId);
set({ set({
tabs: tabs tabs: tabs
}); });
@@ -211,7 +211,6 @@ export const useTabStore = create<TabStore>(
focusEmptyTab: () => { focusEmptyTab: () => {
const index = get().tabs.findIndex((t) => !t.noteId); const index = get().tabs.findIndex((t) => !t.noteId);
if (index === -1) return get().newTab(); if (index === -1) return get().newTab();
console.log("focus empty tab", get().tabs[index]);
get().focusTab(get().tabs[index].id); get().focusTab(get().tabs[index].id);
}, },
@@ -225,7 +224,6 @@ export const useTabStore = create<TabStore>(
}, },
focusTab: (id: number) => { focusTab: (id: number) => {
console.log(history.getHistory(), id);
history.add(id); history.add(id);
set({ set({
currentTab: id currentTab: id

View File

@@ -135,7 +135,6 @@ export const waitForEvent = async (
}; };
eSubscribeEvent(type, callback); eSubscribeEvent(type, callback);
setTimeout(() => { setTimeout(() => {
console.log("return..");
eUnSubscribeEvent(type, callback); eUnSubscribeEvent(type, callback);
resolve(false); resolve(false);
}, waitFor); }, waitFor);
@@ -158,6 +157,9 @@ const canRestoreAppState = (appState: AppState) => {
}; };
let appState: AppState | undefined; let appState: AppState | undefined;
export function setAppState(state: AppState) {
appState = state;
}
export function getAppState() { export function getAppState() {
if (appState && canRestoreAppState(appState)) return appState as AppState; if (appState && canRestoreAppState(appState)) return appState as AppState;
const json = NotesnookModule.getAppState(); const json = NotesnookModule.getAppState();

View File

@@ -0,0 +1,169 @@
/*
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 { Note, VirtualizedGrouping } from "@notesnook/core";
import { useThemeColors } from "@notesnook/theme";
import React, { useEffect, useState } from "react";
import { FlatList, TouchableOpacity, View } from "react-native";
import { db } from "../../common/database";
import { Header } from "../../components/header";
import Input from "../../components/ui/input";
import Paragraph from "../../components/ui/typography/paragraph";
import { useDBItem } from "../../hooks/use-db-item";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { useSettingStore } from "../../stores/use-setting-store";
import { NotesnookModule } from "../../utils/notesnook-module";
const NoteItem = (props: {
id: string | number;
items?: VirtualizedGrouping<Note>;
}) => {
const { colors } = useThemeColors();
const [item] = useDBItem(props.id, "note", props.items);
return (
<TouchableOpacity
activeOpacity={0.7}
onPress={() => {
const widgetId = NotesnookModule.getWidgetId();
NotesnookModule.setString(
"appPreview",
String(widgetId),
JSON.stringify(item)
);
setTimeout(() => {
NotesnookModule.saveAndFinish();
});
}}
style={{
flexDirection: "column",
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
justifyContent: "center",
paddingVertical: 12,
minHeight: 45
}}
>
{!item ? null : (
<View
style={{
flexDirection: "row",
paddingHorizontal: 12
}}
>
<View
style={{
flexDirection: "column"
}}
>
<Paragraph
numberOfLines={1}
style={{
color: colors.primary.paragraph,
fontSize: 15
}}
>
{item.title}
</Paragraph>
</View>
</View>
)}
</TouchableOpacity>
);
};
export const NotePreviewConfigure = () => {
const [items, setItems] = useState<VirtualizedGrouping<Note>>();
const loading = useSettingStore((state) => state.isAppLoading);
const bounceRef = React.useRef<NodeJS.Timeout>();
const { colors } = useThemeColors();
const insets = useGlobalSafeAreaInsets();
useEffect(() => {
useSettingStore.getState().setDeviceMode("mobile");
if (loading) return;
db.notes.all.sorted(db.settings.getGroupOptions("notes")).then((notes) => {
setItems(notes);
});
}, [loading]);
const renderItem = React.useCallback(
({ index }: { item: boolean; index: number }) => {
return <NoteItem id={index} items={items} />;
},
[items]
);
return (
<View
style={{
backgroundColor: colors.primary.background,
flex: 1
}}
>
<Header
canGoBack
title="Select a note"
onLeftMenuButtonPress={() => {
NotesnookModule.cancelAndFinish();
}}
/>
<View
style={{
paddingHorizontal: 12,
paddingTop: 6
}}
>
<Input
placeholder="Search for notes"
containerStyle={{
height: 50
}}
onChangeText={(value) => {
bounceRef.current = setTimeout(() => {
if (!value) {
db.notes.all
.sorted(db.settings.getGroupOptions("notes"))
.then((notes) => {
setItems(notes);
});
return;
}
db.lookup
.notes(value)
.sorted()
.then((notes) => {
setItems(notes);
});
}, 500);
}}
/>
<FlatList
data={items?.placeholders}
keyboardShouldPersistTaps="handled"
keyboardDismissMode="interactive"
renderItem={renderItem}
windowSize={1}
ListFooterComponent={<View style={{ height: 200 }} />}
/>
</View>
</View>
);
};

View File

@@ -284,14 +284,13 @@ NotebookScreen.navigate = async (item: Notebook, canGoBack?: boolean) => {
focusedRouteId == item?.id focusedRouteId == item?.id
) { ) {
// Update the route in place instead // Update the route in place instead
console.log("Updating existing route in place");
eSendEvent(eUpdateNotebookRoute, { eSendEvent(eUpdateNotebookRoute, {
item: item, item: item,
title: item.title, title: item.title,
canGoBack: canGoBack canGoBack: canGoBack
}); });
} else { } else {
console.log("Pushing new notebook route");
// Push a new route // Push a new route
Navigation.push("Notebook", { Navigation.push("Notebook", {
title: item.title, title: item.title,

View File

@@ -59,7 +59,6 @@ ColoredNotes.navigate = (item: Color, canGoBack: boolean) => {
const { focusedRouteId } = useNavigationStore.getState(); const { focusedRouteId } = useNavigationStore.getState();
if (focusedRouteId === item.id) { if (focusedRouteId === item.id) {
console.log("ColoredNotes.navigate: route already focused for color");
return; return;
} }

View File

@@ -171,7 +171,6 @@ const NotesPage = ({
setLoadingNotes(false); setLoadingNotes(false);
}) })
.catch((e) => { .catch((e) => {
console.log("Error loading notes", params.current?.title, e, e.stack);
setLoadingNotes(false); setLoadingNotes(false);
}); });
} }

View File

@@ -60,7 +60,6 @@ TaggedNotes.navigate = (item: Tag, canGoBack?: boolean) => {
const { focusedRouteId } = useNavigationStore.getState(); const { focusedRouteId } = useNavigationStore.getState();
if (focusedRouteId === item.id) { if (focusedRouteId === item.id) {
console.log("TaggedNotes.navigate: route already focused for tag");
return; return;
} }

View File

@@ -160,9 +160,7 @@ export default function DebugLogs() {
type: "success" type: "success"
}); });
} }
} catch (e) { } catch (e) {}
console.log(e);
}
}, [currentLog?.logs]); }, [currentLog?.logs]);
const copyLogs = React.useCallback(() => { const copyLogs = React.useCallback(() => {

View File

@@ -54,7 +54,9 @@ export const Licenses = () => {
}} }}
onPress={() => { onPress={() => {
if (!item.link) return; if (!item.link) return;
Linking.openURL(item.link).catch(console.log); Linking.openURL(item.link).catch(() => {
/* empty */
});
}} }}
> >
<Heading size={SIZE.sm}>{item.name}</Heading> <Heading size={SIZE.sm}>{item.name}</Heading>

View File

@@ -33,7 +33,6 @@ import { strings } from "@notesnook/intl";
export const FontPicker = createSettingsPicker({ export const FontPicker = createSettingsPicker({
getValue: () => useSettingStore.getState().settings.defaultFontFamily, getValue: () => useSettingStore.getState().settings.defaultFontFamily,
updateValue: (item) => { updateValue: (item) => {
console.log(item.id);
SettingsService.set({ SettingsService.set({
defaultFontFamily: item.id defaultFontFamily: item.id
}); });

View File

@@ -197,7 +197,6 @@ const restoreBackup = async (options: {
const attachment = await db.attachments.attachment(hash as string); const attachment = await db.attachments.attachment(hash as string);
if (!attachment) continue; if (!attachment) continue;
console.log("Saving attachment file", hash);
await deleteCacheFileByName(hash); await deleteCacheFileByName(hash);
await RNFetchBlob.fs.cp( await RNFetchBlob.fs.cp(
`${zipOutputFolder}/attachments/${hash}`, `${zipOutputFolder}/attachments/${hash}`,
@@ -208,9 +207,13 @@ const restoreBackup = async (options: {
progress: strings.cleaningUp() progress: strings.cleaningUp()
}); });
// Remove files from cache // Remove files from cache
RNFetchBlob.fs.unlink(zipOutputFolder).catch(console.log); RNFetchBlob.fs.unlink(zipOutputFolder).catch(() => {
/* empty */
});
if (Platform.OS === "android" || deleteBackupFile) { if (Platform.OS === "android" || deleteBackupFile) {
RNFetchBlob.fs.unlink(filePath).catch(console.log); RNFetchBlob.fs.unlink(filePath).catch(() => {
/* empty */
});
} }
} else { } else {
updateProgress({ updateProgress({

View File

@@ -389,7 +389,12 @@ export const settingsGroups: SettingSection[] = [
useHook: () => { useHook: () => {
const [cacheSize, setCacheSize] = React.useState(0); const [cacheSize, setCacheSize] = React.useState(0);
React.useEffect(() => { React.useEffect(() => {
filesystem.getCacheSize().then(setCacheSize).catch(console.log); filesystem
.getCacheSize()
.then(setCacheSize)
.catch(() => {
/* empty */
});
const sub = eSubscribeEvent("cache-cleared", () => { const sub = eSubscribeEvent("cache-cleared", () => {
setCacheSize(0); setCacheSize(0);
}); });
@@ -532,7 +537,7 @@ export const settingsGroups: SettingSection[] = [
endProgress(); endProgress();
} catch (e) { } catch (e) {
endProgress(); endProgress();
console.log(e);
ToastManager.error( ToastManager.error(
e as Error, e as Error,
strings.failedToDeleteAccount(), strings.failedToDeleteAccount(),
@@ -568,7 +573,9 @@ export const settingsGroups: SettingSection[] = [
} }
PremiumService.verify(() => { PremiumService.verify(() => {
SettingsService.setProperty("offlineMode", true); SettingsService.setProperty("offlineMode", true);
db.attachments.cacheAttachments().catch(console.log); db.attachments.cacheAttachments().catch(() => {
/* empty */
});
}); });
} }
}, },
@@ -1459,7 +1466,9 @@ export const settingsGroups: SettingSection[] = [
name: strings.joinTelegram(), name: strings.joinTelegram(),
description: strings.joinTelegramDesc(), description: strings.joinTelegramDesc(),
modifer: () => { modifer: () => {
Linking.openURL("https://t.me/notesnook").catch(console.log); Linking.openURL("https://t.me/notesnook").catch(() => {
/* empty */
});
} }
}, },
{ {
@@ -1479,7 +1488,9 @@ export const settingsGroups: SettingSection[] = [
description: strings.followOnXDesc(), description: strings.followOnXDesc(),
icon: "twitter", icon: "twitter",
modifer: () => { modifer: () => {
Linking.openURL("https://twitter.com/notesnook").catch(console.log); Linking.openURL("https://twitter.com/notesnook").catch(() => {
/* empty */
});
} }
}, },
{ {
@@ -1487,7 +1498,9 @@ export const settingsGroups: SettingSection[] = [
name: strings.joinDiscord(), name: strings.joinDiscord(),
icon: "discord", icon: "discord",
modifer: async () => { modifer: async () => {
Linking.openURL("https://discord.gg/zQBK97EE22").catch(console.log); Linking.openURL("https://discord.gg/zQBK97EE22").catch(() => {
/* empty */
});
}, },
description: strings.joinDiscordDesc() description: strings.joinDiscordDesc()
} }

View File

@@ -25,6 +25,7 @@ import {
import { DatabaseLogger, db, setupDatabase } from "../common/database"; import { DatabaseLogger, db, setupDatabase } from "../common/database";
import { deleteDCacheFiles } from "../common/filesystem/io"; import { deleteDCacheFiles } from "../common/filesystem/io";
import { useUserStore } from "../stores/use-user-store"; import { useUserStore } from "../stores/use-user-store";
import { NotePreviewWidget } from "./note-preview-widget";
import Notifications from "./notifications"; import Notifications from "./notifications";
import SettingsService from "./settings"; import SettingsService from "./settings";
@@ -85,7 +86,6 @@ const task = async (event: { taskId: string; timeout: boolean }) => {
const taskId = event.taskId; const taskId = event.taskId;
const isTimeout = event.timeout; // <-- true when your background-time has expired. const isTimeout = event.timeout; // <-- true when your background-time has expired.
if (isTimeout) { if (isTimeout) {
console.log(`BACKGROUND FETCH TIMEOUT: ${taskId}`);
BackgroundFetch.finish(taskId); BackgroundFetch.finish(taskId);
return; return;
} }
@@ -112,12 +112,13 @@ async function onBackgroundSyncStarted() {
useUserStore.getState().setSyncing(false); useUserStore.getState().setSyncing(false);
} }
await Notifications.setupReminders(); await Notifications.setupReminders();
NotePreviewWidget.updateNotes();
deleteDCacheFiles(); deleteDCacheFiles();
DatabaseLogger.info("BACKGROUND SYNC COMPLETE"); DatabaseLogger.info("BACKGROUND SYNC COMPLETE");
} catch (e) { } catch (e) {
useUserStore.getState().setSyncing(false); useUserStore.getState().setSyncing(false);
DatabaseLogger.error(e as Error); DatabaseLogger.error(e as Error);
console.log("BACKGROUND SYNC ERROR", (e as Error).message);
} }
} }
@@ -142,7 +143,6 @@ const onBoot = async () => {
DatabaseLogger.info("BOOT TASK COMPLETE"); DatabaseLogger.info("BOOT TASK COMPLETE");
} catch (e) { } catch (e) {
DatabaseLogger.error(e as Error); DatabaseLogger.error(e as Error);
console.log(e);
} }
}; };

View File

@@ -120,13 +120,17 @@ async function presentBackupCompleteSheet(backupFilePath: string) {
Share.open({ Share.open({
url: backupFilePath, url: backupFilePath,
failOnCancel: false failOnCancel: false
}).catch(console.log); }).catch(() => {
/* empty */
});
} else { } else {
FileViewer.open(backupFilePath, { FileViewer.open(backupFilePath, {
showOpenWithDialog: true, showOpenWithDialog: true,
showAppsSuggestions: true, showAppsSuggestions: true,
shareFile: true shareFile: true
} as any).catch(console.log); } as any).catch(() => {
/* empty */
});
} }
}, },
actionText: strings.share() actionText: strings.share()
@@ -161,8 +165,6 @@ async function run(
context?: string, context?: string,
backupType: "full" | "partial" = "partial" backupType: "full" | "partial" = "partial"
) { ) {
console.log("Creating backup:", backupType, progress, context);
const androidBackupDirectory = (await checkBackupDirExists( const androidBackupDirectory = (await checkBackupDirExists(
false, false,
context context
@@ -203,7 +205,9 @@ async function run(
? `${path}/${backupFileName}.nnbackupz` ? `${path}/${backupFileName}.nnbackupz`
: `${cacheDir}/${backupFileName}.nnbackupz`; : `${cacheDir}/${backupFileName}.nnbackupz`;
await RNFetchBlob.fs.unlink(zipSourceFolder).catch(console.log); await RNFetchBlob.fs.unlink(zipSourceFolder).catch(() => {
/* empty */
});
await RNFetchBlob.fs.mkdir(zipSourceFolder); await RNFetchBlob.fs.mkdir(zipSourceFolder);
const attachmentsDir = zipSourceFolder + "/attachments"; const attachmentsDir = zipSourceFolder + "/attachments";
@@ -253,18 +257,21 @@ async function run(
`${backupFileName}.nnbackupz`, `${backupFileName}.nnbackupz`,
"application/nnbackupz" "application/nnbackupz"
); );
console.log("Copying zip file...");
await copyFileAsync(`file://${zipOutputFile}`, file.uri); await copyFileAsync(`file://${zipOutputFile}`, file.uri);
console.log("Copied zip file...");
path = file.uri; path = file.uri;
} else { } else {
path = zipOutputFile; path = zipOutputFile;
} }
RNFetchBlob.fs.unlink(zipSourceFolder).catch(console.log); RNFetchBlob.fs.unlink(zipSourceFolder).catch(() => {
/* empty */
});
if (Platform.OS === "android") { if (Platform.OS === "android") {
RNFetchBlob.fs.unlink(zipOutputFile).catch(console.log); RNFetchBlob.fs.unlink(zipOutputFile).catch(() => {
/* empty */
});
} }
updateNextBackupTime(backupType || "partial"); updateNextBackupTime(backupType || "partial");
@@ -308,9 +315,13 @@ async function run(
return run(progress, context, backupType); return run(progress, context, backupType);
} }
RNFetchBlob.fs.unlink(zipSourceFolder).catch(console.log); RNFetchBlob.fs.unlink(zipSourceFolder).catch(() => {
/* empty */
});
if (Platform.OS === "android") { if (Platform.OS === "android") {
RNFetchBlob.fs.unlink(zipOutputFile).catch(console.log); RNFetchBlob.fs.unlink(zipOutputFile).catch(() => {
/* empty */
});
} }
DatabaseLogger.error(e); DatabaseLogger.error(e);
@@ -329,7 +340,6 @@ async function checkBackupRequired(
type: "daily" | "off" | "useroff" | "weekly" | "monthly" | "never", type: "daily" | "off" | "useroff" | "weekly" | "monthly" | "never",
lastBackupDateType: "lastBackupDate" | "lastFullBackupDate" = "lastBackupDate" lastBackupDateType: "lastBackupDate" | "lastFullBackupDate" = "lastBackupDate"
) { ) {
console.log(lastBackupDateType, type);
if (type === "off" || type === "useroff" || type === "never" || !type) return; if (type === "off" || type === "useroff" || type === "never" || !type) return;
const now = Date.now(); const now = Date.now();
const lastBackupDate = SettingsService.getProperty(lastBackupDateType) as const lastBackupDate = SettingsService.getProperty(lastBackupDateType) as
@@ -362,9 +372,7 @@ const checkAndRun = async () => {
if (await checkBackupRequired(settings?.reminder)) { if (await checkBackupRequired(settings?.reminder)) {
try { try {
await run(); await run();
} catch (e) { } catch (e) {}
console.log(e);
}
} }
}; };

View File

@@ -123,7 +123,6 @@ export type PresentSheetOptions = {
}; };
export function presentSheet(data: Partial<PresentSheetOptions>) { export function presentSheet(data: Partial<PresentSheetOptions>) {
console.log("PRESENTING...");
eSendEvent(eOpenSheet, data); eSendEvent(eOpenSheet, data);
} }

View File

@@ -85,7 +85,7 @@ async function resolveFileFunctions(
`/export_${Date.now()}` `/export_${Date.now()}`
); );
await RNFetchBlob.fs.mkdir(exportCacheFolder).catch((e) => console.log(e)); await RNFetchBlob.fs.mkdir(exportCacheFolder).catch((e) => {});
const mkdir = async (dir: string) => { const mkdir = async (dir: string) => {
const folder = join(exportCacheFolder, dir); const folder = join(exportCacheFolder, dir);
@@ -96,7 +96,7 @@ async function resolveFileFunctions(
const writeFile = async (path: string, result: string) => { const writeFile = async (path: string, result: string) => {
const cacheFilePath = join(exportCacheFolder, path); const cacheFilePath = join(exportCacheFolder, path);
console.log(cacheFilePath, result.length);
await RNFetchBlob.fs.writeFile( await RNFetchBlob.fs.writeFile(
cacheFilePath, cacheFilePath,
result, result,
@@ -194,7 +194,7 @@ async function bulkExport(
try { try {
await exportNoteToFile(item, type, mkdir, writeFile); await exportNoteToFile(item, type, mkdir, writeFile);
} catch (e) { } catch (e) {
console.log(item.type, e); /* empty */
} }
} else if (item.type === "attachment") { } else if (item.type === "attachment") {
currentAttachmentProgress += 1; currentAttachmentProgress += 1;
@@ -202,11 +202,11 @@ async function bulkExport(
try { try {
await exportAttachmentToFile(item, mkdir, cacheFolder); await exportAttachmentToFile(item, mkdir, cacheFolder);
} catch (e) { } catch (e) {
console.log(item.path, e); /* empty */
} }
} }
} }
console.log(cacheFolder);
return createZip(totalNotes, cacheFolder, type, path, callback); return createZip(totalNotes, cacheFolder, type, path, callback);
} }
@@ -240,7 +240,7 @@ async function exportNote(
noteItem = item; noteItem = item;
await exportNoteToFile(item, type, mkdir, writeFile); await exportNoteToFile(item, type, mkdir, writeFile);
} catch (e) { } catch (e) {
console.log("exportNoteToFile", item.type, e); /* empty */
} }
} else if (item.type === "attachment") { } else if (item.type === "attachment") {
currentAttachmentProgress += 1; currentAttachmentProgress += 1;
@@ -249,13 +249,12 @@ async function exportNote(
hasAttachments = true; hasAttachments = true;
await exportAttachmentToFile(item, mkdir, cacheFolder); await exportAttachmentToFile(item, mkdir, cacheFolder);
} catch (e) { } catch (e) {
console.log("exportAttachmentToFile", item.path, e); /* empty */
} }
} }
} }
if (!hasAttachments) { if (!hasAttachments) {
console.log("creating file...");
return createFile(noteItem as ExportableNote, type, path, cacheFolder); return createFile(noteItem as ExportableNote, type, path, cacheFolder);
} else { } else {
return createZip(1, cacheFolder, type, path, callback); return createZip(1, cacheFolder, type, path, callback);
@@ -333,10 +332,10 @@ async function createFile(
filePath = originalPath.replace(`${ext}`, "") + "_" + id + ext; filePath = originalPath.replace(`${ext}`, "") + "_" + id + ext;
id++; id++;
} }
console.log("path", filePath);
await RNFetchBlob.fs.mv(exportedFile, filePath); await RNFetchBlob.fs.mv(exportedFile, filePath);
} }
console.log("file moved...");
return { return {
filePath: filePath, filePath: filePath,
fileDir: path, fileDir: path,

View 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 { Platform } from "react-native";
import { db } from "../common/database";
import ReminderSheet from "../components/sheets/reminder";
import { setAppState } from "../screens/editor/tiptap/utils";
import { eOnLoadNote } from "../utils/events";
import { tabBarRef } from "../utils/global-refs";
import { NotesnookModule } from "../utils/notesnook-module";
import { eSendEvent } from "./event-manager";
const launchIntent = Platform.OS === "ios" ? {} : NotesnookModule.getIntent();
let used = false;
let launched = false;
export const IntentService = {
getLaunchIntent() {
if (used || Platform.OS === "ios") return null;
used = true;
return launchIntent;
},
onLaunch() {
if (launched || Platform.OS === "ios") return;
launched = true;
if (launchIntent["com.streetwriters.notesnook.OpenNoteId"]) {
setAppState({
movedAway: false,
editing: true,
timestamp: Date.now(),
noteId: launchIntent["com.streetwriters.notesnook.OpenNoteId"]
});
}
},
async onAppStateChanged() {
if (Platform.OS === "ios") return;
const intent = NotesnookModule.getIntent();
if (intent["com.streetwriters.notesnook.OpenNoteId"]) {
const note = await db.notes.note(
intent["com.streetwriters.notesnook.OpenNoteId"]
);
if (note) {
eSendEvent(eOnLoadNote, {
item: note
});
tabBarRef.current?.goToPage(1, false);
}
} else if (intent["com.streetwriters.notesnook.OpenReminderId"]) {
const reminder = await db.reminders.reminder(
intent["com.streetwriters.notesnook.OpenReminderId"]
);
if (reminder) ReminderSheet.present(reminder);
} else if (intent["com.streetwriters.notesnook.NewReminder"]) {
ReminderSheet.present();
}
}
};

View File

@@ -122,7 +122,6 @@ function queueRoutesForUpdate(...routesToUpdate: RouteName[]) {
} }
function navigate<T extends RouteName>(screen: T, params?: RouteParams[T]) { function navigate<T extends RouteName>(screen: T, params?: RouteParams[T]) {
console.log(`Navigation.navigate ${screen} route`);
rootNavigatorRef.current?.navigate(screen as any, params); rootNavigatorRef.current?.navigate(screen as any, params);
} }
@@ -131,17 +130,14 @@ function goBack() {
} }
function push<T extends RouteName>(screen: T, params: RouteParams[T]) { function push<T extends RouteName>(screen: T, params: RouteParams[T]) {
console.log(`Navigation.push ${screen} route`);
rootNavigatorRef.current?.dispatch(StackActions.push(screen as any, params)); rootNavigatorRef.current?.dispatch(StackActions.push(screen as any, params));
} }
function replace<T extends RouteName>(screen: T, params: RouteParams[T]) { function replace<T extends RouteName>(screen: T, params: RouteParams[T]) {
console.log(`Navigation.replace ${screen} route`);
rootNavigatorRef.current?.dispatch(StackActions.replace(screen, params)); rootNavigatorRef.current?.dispatch(StackActions.replace(screen, params));
} }
function popToTop() { function popToTop() {
console.log(`Navigation.popToTop`);
rootNavigatorRef.current?.dispatch(StackActions.popToTop()); rootNavigatorRef.current?.dispatch(StackActions.popToTop());
} }

View 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 { Note } from "@notesnook/core";
import { db } from "../common/database";
import { NotesnookModule } from "../utils/notesnook-module";
import { Platform } from "react-native";
let timer: NodeJS.Timeout;
export const NotePreviewWidget = {
updateNotes: () => {
if (Platform.OS !== "android") return;
clearTimeout(timer);
timer = setTimeout(async () => {
const noteIds = await NotesnookModule.getWidgetNotes();
for (const id of noteIds) {
const newNote = await db.notes.note(id);
if (!newNote) continue;
NotesnookModule.updateWidgetNote(id, JSON.stringify(newNote));
}
}, 500);
},
updateNote: async (id: string, note: Note) => {
if (Platform.OS !== "android") return;
if (id && (await NotesnookModule.hasWidgetNote(id))) {
NotesnookModule.updateWidgetNote(id, JSON.stringify(note));
}
}
};

View File

@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { Reminder } from "@notesnook/core"; import { isReminderActive, Reminder } from "@notesnook/core";
import { strings } from "@notesnook/intl"; import { strings } from "@notesnook/intl";
import notifee, { import notifee, {
AndroidStyle, AndroidStyle,
@@ -51,6 +51,7 @@ import { DDS } from "./device-detection";
import { eSendEvent } from "./event-manager"; import { eSendEvent } from "./event-manager";
import Navigation from "./navigation"; import Navigation from "./navigation";
import SettingsService from "./settings"; import SettingsService from "./settings";
import { getFormattedReminderTime } from "@notesnook/common";
let pinned: DisplayedNotification[] = []; let pinned: DisplayedNotification[] = [];
@@ -120,7 +121,7 @@ const onEvent = async ({ type, detail }: Event) => {
await scheduleNotification(reminder); await scheduleNotification(reminder);
} }
} }
updateRemindersForWidget();
return; return;
} }
if (type === EventType.PRESS) { if (type === EventType.PRESS) {
@@ -141,7 +142,7 @@ const onEvent = async ({ type, detail }: Event) => {
} }
editorState().movedAway = false; editorState().movedAway = false;
const noteId = notification?.id; const noteId = notification?.id;
console.log("NOTE ID", noteId);
loadNote(noteId as string, true); loadNote(noteId as string, true);
} }
@@ -167,6 +168,7 @@ const onEvent = async ({ type, detail }: Event) => {
); );
useRelationStore.getState().update(); useRelationStore.getState().update();
useReminderStore.getState().refresh(); useReminderStore.getState().refresh();
updateRemindersForWidget();
break; break;
} }
case "REMINDER_DISABLE": { case "REMINDER_DISABLE": {
@@ -184,6 +186,7 @@ const onEvent = async ({ type, detail }: Event) => {
); );
useRelationStore.getState().update(); useRelationStore.getState().update();
useReminderStore.getState().refresh(); useReminderStore.getState().refresh();
updateRemindersForWidget();
break; break;
} }
case strings.unpin(): { case strings.unpin(): {
@@ -235,11 +238,9 @@ const onEvent = async ({ type, detail }: Event) => {
try { try {
if (!globalThis["IS_MAIN_APP_RUNNING" as never]) { if (!globalThis["IS_MAIN_APP_RUNNING" as never]) {
await db.sync({ type: "send", force: false }); await db.sync({ type: "send", force: false });
} else {
console.log("main app running, skipping sync");
} }
} catch (e) { } catch (e) {
console.log(e, (e as Error).stack); /* empty */
} }
} }
Navigation.queueRoutesForUpdate(); Navigation.queueRoutesForUpdate();
@@ -249,6 +250,35 @@ const onEvent = async ({ type, detail }: Event) => {
} }
}; };
type ReminderWithFormattedTime = Reminder & {
formattedTime?: string;
};
async function updateRemindersForWidget() {
if (Platform.OS === "ios") return;
const reminders: ReminderWithFormattedTime[] = await db.reminders?.all.items(
undefined,
{
sortBy: "dueDate",
sortDirection: "desc"
}
);
const activeReminders = [];
if (!reminders) return;
for (const reminder of reminders) {
if (isReminderActive(reminder)) {
reminder.formattedTime = getFormattedReminderTime(reminder);
activeReminders.push(reminder);
}
}
NotesnookModule.setString(
"appPreview",
"remindersList",
JSON.stringify(activeReminders)
);
NotesnookModule.updateReminderWidget();
}
async function setupIOSCategories() { async function setupIOSCategories() {
try { try {
if (Platform.OS === "ios") { if (Platform.OS === "ios") {
@@ -288,7 +318,7 @@ async function setupIOSCategories() {
} }
} }
} catch (e) { } catch (e) {
console.log("ERROR in setupIOSCategories", e); /* empty */
} }
} }
@@ -398,8 +428,9 @@ async function scheduleNotification(
trigger trigger
); );
} }
updateRemindersForWidget();
} catch (e) { } catch (e) {
console.log("Schedule notification", e); /* empty */
} }
} }
@@ -542,7 +573,7 @@ async function displayNotification({
} }
}); });
} catch (e) { } catch (e) {
console.log(e); /* empty */
} }
} }
@@ -943,6 +974,7 @@ async function setupReminders(checkNeedsScheduling = false) {
trigger.notification.id && trigger.notification.id &&
notifee.cancelTriggerNotification(trigger.notification.id as string) notifee.cancelTriggerNotification(trigger.notification.id as string)
); );
updateRemindersForWidget();
} }
async function pinNote(id: string) { async function pinNote(id: string) {
@@ -963,7 +995,7 @@ async function pinNote(id: string) {
id: note.id id: note.id
}); });
} catch (e) { } catch (e) {
console.log(e); /* empty */
} }
} }
const Events = { const Events = {
@@ -988,7 +1020,8 @@ const Notifications = {
getChannelId, getChannelId,
isNotePinned, isNotePinned,
pinNote, pinNote,
Events Events,
updateRemindersForWidget
}; };
export default Notifications; export default Notifications;

View File

@@ -76,9 +76,7 @@ async function setPremiumStatus() {
products = await RNIap.getSubscriptions({ products = await RNIap.getSubscriptions({
skus: itemSkus skus: itemSkus
}); });
} catch (e) { } catch (e) {}
console.log("subscriptions: ", e);
}
if (premiumStatus === 0 && !__DEV__) { if (premiumStatus === 0 && !__DEV__) {
SettingsService.reset(); SettingsService.reset();
} }
@@ -299,7 +297,6 @@ const subscriptions = {
} }
}; };
console.log("Subscription.verify", requestData);
try { try {
let result = await fetch( let result = await fetch(
__DEV__ __DEV__
@@ -307,7 +304,7 @@ const subscriptions = {
: "https://payments.streetwriters.co/apple/verify", : "https://payments.streetwriters.co/apple/verify",
requestData requestData
); );
console.log("Subscribed", result);
let text = await result.text(); let text = await result.text();
if (!result.ok) { if (!result.ok) {
@@ -318,9 +315,7 @@ const subscriptions = {
} else { } else {
await subscriptions.clear(subscription); await subscriptions.clear(subscription);
} }
} catch (e) { } catch (e) {}
console.log("subscription error", e);
}
} }
} }
}, },

View File

@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { db } from "../common/database"; import { db } from "../common/database";
import Navigation from "../services/navigation"; import Navigation from "../services/navigation";
import { NotePreviewWidget } from "../services/note-preview-widget";
import Notifications from "../services/notifications"; import Notifications from "../services/notifications";
import { useFavoriteStore } from "./use-favorite-store"; import { useFavoriteStore } from "./use-favorite-store";
import { useMenuStore } from "./use-menu-store"; import { useMenuStore } from "./use-menu-store";
@@ -41,6 +42,8 @@ export function initAfterSync() {
useUserStore.setState({ useUserStore.setState({
profile: db.settings.getProfile() profile: db.settings.getProfile()
}); });
NotePreviewWidget.updateNotes();
} }
export async function initialize() {} export async function initialize() {}

View File

@@ -80,7 +80,6 @@ export const useMenuStore = create<MenuStore>((set, get) => ({
JSON.stringify(get().hiddenItems || {}) !== JSON.stringify(get().hiddenItems || {}) !==
JSON.stringify(hiddenItems || {}) JSON.stringify(hiddenItems || {})
) { ) {
console.log(order, hiddenItems);
set({ set({
order: order, order: order,
hiddenItems: hiddenItems hiddenItems: hiddenItems

View File

@@ -126,7 +126,6 @@ export const useMessageStore = create<MessageStore>((set, get) => ({
announcements = []; announcements = [];
} }
} catch (e) { } catch (e) {
console.log(e);
set({ announcements: [] }); set({ announcements: [] });
} finally { } finally {
const all = await getFiltered(announcements); const all = await getFiltered(announcements);

View File

@@ -106,7 +106,6 @@ const useNavigationStore = create<NavigationStore>((set, get) => ({
set({ set({
focusedRouteId: id focusedRouteId: id
}); });
console.log("CurrentRoute ID", id);
}, },
currentRoute: "Notes", currentRoute: "Notes",
canGoBack: false, canGoBack: false,
@@ -114,7 +113,6 @@ const useNavigationStore = create<NavigationStore>((set, get) => ({
set({ set({
currentRoute: currentScreen currentRoute: currentScreen
}); });
console.log("CurrentRoute", currentScreen);
}, },
headerRightButtons: [], headerRightButtons: [],
buttonAction: () => null, buttonAction: () => null,

View File

@@ -49,7 +49,7 @@ export async function attachFile(uri, hash, type, filename, options) {
encryptionInfo.filename = filename; encryptionInfo.filename = filename;
encryptionInfo.alg = "xcha-stream"; encryptionInfo.alg = "xcha-stream";
encryptionInfo.key = key; encryptionInfo.key = key;
console.log(encryptionInfo);
if (options?.reupload && exists) await db.attachments.reset(hash); if (options?.reupload && exists) await db.attachments.reset(hash);
} else { } else {
encryptionInfo = { hash: hash }; encryptionInfo = { hash: hash };
@@ -57,9 +57,12 @@ export async function attachFile(uri, hash, type, filename, options) {
await db.attachments.add(encryptionInfo, options?.id); await db.attachments.add(encryptionInfo, options?.id);
return true; return true;
} catch (e) { } catch (e) {
if (Platform.OS === "ios") RNFetchBlob.fs.unlink(uri).catch(console.log); if (Platform.OS === "ios")
RNFetchBlob.fs.unlink(uri).catch(() => {
/* empty */
});
DatabaseLogger.error(e, "Attach file error"); DatabaseLogger.error(e, "Attach file error");
console.log("attach file error: ", e);
return false; return false;
} }
} }
@@ -102,12 +105,10 @@ async function createNotes(bundle) {
const isJpeg = /(jpeg|jpg)/g.test(file.type); const isJpeg = /(jpeg|jpg)/g.test(file.type);
if ((isPng || isJpeg) && compress) { if ((isPng || isJpeg) && compress) {
console.log(uri, "before compressed");
uri = await compressToFile("file://" + uri, isPng ? "PNG" : "JPEG"); uri = await compressToFile("file://" + uri, isPng ? "PNG" : "JPEG");
uri = `${uri.replace("file://", "")}`; uri = `${uri.replace("file://", "")}`;
} }
console.log(uri, "after compressed");
const hash = await Sodium.hashFile({ const hash = await Sodium.hashFile({
uri: uri, uri: uri,

View File

@@ -25,6 +25,21 @@ interface NotesnookModuleInterface {
setSecureMode: (enabled: boolean) => void; setSecureMode: (enabled: boolean) => void;
setAppState: (appState: string) => void; setAppState: (appState: string) => void;
getAppState: () => string; getAppState: () => string;
saveAndFinish: () => void;
setString: (storeName: string, key: string, value: string) => void;
getString: (storeName: string, key: string) => Promise<string>;
removeString: (key: string) => void;
cancelAndFinish: () => void;
getWidgetId: () => void;
getIntent: () => {
"com.streetwriters.notesnook.OpenNoteId"?: string;
"com.streetwriters.notesnook.OpenReminderId"?: string;
"com.streetwriters.notesnook.NewReminder"?: string;
};
getWidgetNotes: () => Promise<string[]>;
hasWidgetNote: (noteId: string) => Promise<boolean>;
updateWidgetNote: (noteId: string, data: string) => void;
updateReminderWidget: () => void;
} }
export const NotesnookModule: NotesnookModuleInterface = Platform.select({ export const NotesnookModule: NotesnookModuleInterface = Platform.select({
@@ -33,7 +48,18 @@ export const NotesnookModule: NotesnookModuleInterface = Platform.select({
setBackgroundColor: () => {}, setBackgroundColor: () => {},
setSecureMode: () => {}, setSecureMode: () => {},
setAppState: () => {}, setAppState: () => {},
getAppState: () => {} getAppState: () => {},
saveAndFinish: () => {},
getString: () => {},
setString: () => {},
removeString: () => {},
cancelAndFinish: () => {},
getWidgetId: () => {},
getIntent: () => {},
getWidgetNotes: () => {},
hasWidgetNote: () => {},
updateWidgetNote: () => {},
updateReminderWidget: () => {}
}, },
android: NativeModules.NNativeModule android: NativeModules.NNativeModule
}); });

View File

@@ -212,6 +212,7 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.9.2' implementation 'com.squareup.okhttp3:okhttp:4.9.2'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.2' implementation 'com.squareup.okhttp3:logging-interceptor:4.9.2'
implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.9.2' implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.9.2'
implementation 'com.google.code.gson:gson:2.11.0'
androidTestImplementation('com.wix:detox:+') androidTestImplementation('com.wix:detox:+')
implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.appcompat:appcompat:1.1.0'

View File

@@ -60,10 +60,18 @@
android:theme="@style/BootTheme" android:theme="@style/BootTheme"
android:largeHeap="true" android:largeHeap="true"
android:supportsRtl="false" android:supportsRtl="false"
android:networkSecurityConfig="@xml/network_security_config"
tools:replace="android:supportsRtl"> tools:replace="android:supportsRtl">
<receiver android:exported="false" android:label="@string/reminders_title" android:name=".ReminderWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_reminders_info" />
</receiver>
<receiver android:exported="false" android:name=".NoteWidget"> <receiver android:exported="false" android:label="@string/quick_note" android:name=".NoteWidget">
<intent-filter> <intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter> </intent-filter>
@@ -73,6 +81,27 @@
android:resource="@xml/new_note_widget_info" /> android:resource="@xml/new_note_widget_info" />
</receiver> </receiver>
<receiver android:exported="false" android:label="@string/note" android:name=".NotePreviewWidget">
<intent-filter>"
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/note_widget_info" />
</receiver>
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:label="NotePreviewConfigure"
android:launchMode="singleTask"
android:exported="true"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize" android:name=".NotePreviewConfigureActivity">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
@@ -166,6 +195,11 @@
</intent-filter> </intent-filter>
</service> </service>
<service
android:name=".ReminderViewsService"
android:exported="true"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider" android:authorities="${applicationId}.provider"
@@ -193,9 +227,6 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
</application> </application>
</manifest> </manifest>

View File

@@ -3,7 +3,6 @@ package com.streetwriters.notesnook;
import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivity;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.webkit.WebView; import android.webkit.WebView;
import com.facebook.react.ReactActivityDelegate; import com.facebook.react.ReactActivityDelegate;
@@ -12,22 +11,17 @@ import com.facebook.react.defaults.DefaultReactActivityDelegate;
import com.zoontek.rnbootsplash.RNBootSplash; import com.zoontek.rnbootsplash.RNBootSplash;
public class MainActivity extends ReactActivity { public class MainActivity extends ReactActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
RNBootSplash.init(this); RNBootSplash.init(this);
super.onCreate(null); super.onCreate(null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
WebView.setWebContentsDebuggingEnabled(true); WebView.setWebContentsDebuggingEnabled(true);
} }
try { try {
startService(new Intent(getBaseContext(), OnClearFromRecentService.class)); startService(new Intent(getBaseContext(), OnClearFromRecentService.class));
} catch (Exception e) { } catch (Exception ignored) {}
}
} }
/** /**
@@ -49,7 +43,7 @@ public void onNewIntent(Intent intent) {
setIntent(intent); setIntent(intent);
} }
@Override @Override
public void onConfigurationChanged(Configuration newConfig) { public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig); super.onConfigurationChanged(newConfig);
getReactInstanceManager().onConfigurationChanged(this, newConfig); getReactInstanceManager().onConfigurationChanged(this, newConfig);
@@ -63,7 +57,6 @@ public void onConfigurationChanged(Configuration newConfig) {
return "Notesnook"; return "Notesnook";
} }
@Override @Override
public void invokeDefaultOnBackPressed() { public void invokeDefaultOnBackPressed() {
moveTaskToBack(true); moveTaskToBack(true);

View File

@@ -21,6 +21,7 @@ class MainApplication : Application(), ReactApplication {
// add(MyReactNativePackage()) // add(MyReactNativePackage())
add(NNativeModulePackage()); add(NNativeModulePackage());
} }
override fun getJSMainModuleName(): String = "index" override fun getJSMainModuleName(): String = "index"

View File

@@ -0,0 +1,71 @@
package com.streetwriters.notesnook;
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.RemoteViews;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;
import com.google.gson.Gson;
import com.streetwriters.notesnook.datatypes.Note;
public class NotePreviewConfigureActivity extends ReactActivity {
static int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
static NotePreviewConfigureActivity activity;
/**
* Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
* DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
* (aka React 18) with two boolean flags.
*/
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new DefaultReactActivityDelegate(
this,
getMainComponentName(),
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled
// If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18).
DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled
);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
Intent intent = getIntent();
Bundle extras = intent.getExtras();
int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
if (extras != null) {
appWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
NotePreviewConfigureActivity.appWidgetId = appWidgetId;
}
Intent resultValue = new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(Activity.RESULT_CANCELED, resultValue);
activity = this;
}
public static void saveAndFinish(Context context) {
if (NotePreviewConfigureActivity.activity == null || appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) return;
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
NotePreviewWidget.updateAppWidget(context, appWidgetManager, appWidgetId);
Intent resultValue = new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
NotePreviewConfigureActivity.activity.setResult(RESULT_OK, resultValue);
NotePreviewConfigureActivity.activity.finish();
}
@Override
protected String getMainComponentName() {
return "NotePreviewConfigure";
}
}

View File

@@ -0,0 +1,63 @@
package com.streetwriters.notesnook;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.widget.RemoteViews;
import com.google.gson.Gson;
import com.streetwriters.notesnook.datatypes.Note;
public class NotePreviewWidget extends AppWidgetProvider {
static String OpenNoteId = "com.streetwriters.notesnook.OpenNoteId";
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
String data = context.getSharedPreferences("appPreview", Context.MODE_PRIVATE).getString(String.valueOf(appWidgetId), "");
if (data.isEmpty()) {
return;
}
Gson gson = new Gson();
Note note = gson.fromJson(data, Note.class);
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(OpenNoteId, note.getId());
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, getActivityOptionsBundle());
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.note_widget);
views.setTextViewText(R.id.widget_title, note.getTitle());
views.setTextViewText(R.id.widget_body, note.getHeadline());
views.setOnClickPendingIntent(R.id.widget_button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
private static Bundle getActivityOptionsBundle() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
ActivityOptions activityOptions = ActivityOptions.makeBasic();
activityOptions.setPendingIntentBackgroundActivityStartMode(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return activityOptions.toBundle();
} else
return null;
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
SharedPreferences.Editor edit = context.getSharedPreferences("appPreview", Context.MODE_PRIVATE).edit();
for (int id: appWidgetIds) {
edit.remove(String.valueOf(id));
}
edit.apply();
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
}

View File

@@ -1,10 +1,12 @@
package com.streetwriters.notesnook; package com.streetwriters.notesnook;
import android.app.ActivityOptions;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider; import android.appwidget.AppWidgetProvider;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.widget.RemoteViews; import android.widget.RemoteViews;
@@ -15,16 +17,26 @@ public class NoteWidget extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) { int appWidgetId) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_note_widget);
Intent intent = new Intent(context, ShareActivity.class); setClickIntent(context, views);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.note_widget);
views.setOnClickPendingIntent(R.id.widget_button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views); appWidgetManager.updateAppWidget(appWidgetId, views);
} }
static void setClickIntent(Context context, RemoteViews views) {
Intent intent = new Intent(context, ShareActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, getActivityOptionsBundle());
views.setOnClickPendingIntent(R.id.widget_button, pendingIntent);
}
private static Bundle getActivityOptionsBundle() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
ActivityOptions activityOptions = ActivityOptions.makeBasic();
activityOptions.setPendingIntentBackgroundActivityStartMode(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return activityOptions.toBundle();
} else
return null;
}
@Override @Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
@@ -33,21 +45,20 @@ public class NoteWidget extends AppWidgetProvider {
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle options) { private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle options) {
int minWidth = options != null ? options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) : 0; int minWidth = options != null ? options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) : 0;
// int minHeight = options != null ? options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) : 0; int minHeight = options != null ? options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) : 0;
int layoutId = (minWidth < 100) ? R.layout.note_widget_icon : R.layout.note_widget; int layoutId = (minWidth < 100) ? R.layout.new_note_widget_icon : R.layout.new_note_widget;
RemoteViews views = new RemoteViews(context.getPackageName(), layoutId); RemoteViews views = new RemoteViews(context.getPackageName(), layoutId);
setClickIntent(context, views);
appWidgetManager.updateAppWidget(appWidgetId, views); appWidgetManager.updateAppWidget(appWidgetId, views);
} }
@Override @Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) { for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId); updateAppWidget(context, appWidgetManager, appWidgetId);
updateAppWidget(context, appWidgetManager, appWidgetId,null);
} }
} }
} }

View File

@@ -1,21 +1,35 @@
package com.streetwriters.notesnook; package com.streetwriters.notesnook;
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.RemoteViews;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.google.gson.Gson;
import com.streetwriters.notesnook.datatypes.Note;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class RCTNNativeModule extends ReactContextBaseJavaModule { public class RCTNNativeModule extends ReactContextBaseJavaModule {
Intent lastIntent;
ReactContext mContext; ReactContext mContext;
public RCTNNativeModule(ReactApplicationContext reactContext) { public RCTNNativeModule(ReactApplicationContext reactContext) {
@@ -31,7 +45,6 @@ public class RCTNNativeModule extends ReactContextBaseJavaModule {
@ReactMethod @ReactMethod
public void setBackgroundColor(final String color) { public void setBackgroundColor(final String color) {
try { try {
getCurrentActivity().getWindow().getDecorView().setBackgroundColor(Color.parseColor(color)); getCurrentActivity().getWindow().getDecorView().setBackgroundColor(Color.parseColor(color));
} catch (Exception e) { } catch (Exception e) {
@@ -48,8 +61,6 @@ public class RCTNNativeModule extends ReactContextBaseJavaModule {
} }
} }
@ReactMethod @ReactMethod
public void setSecureMode(final boolean mode) { public void setSecureMode(final boolean mode) {
try { try {
@@ -85,6 +96,118 @@ public class RCTNNativeModule extends ReactContextBaseJavaModule {
return appStateValue.isEmpty() ? null : appStateValue; return appStateValue.isEmpty() ? null : appStateValue;
} }
@ReactMethod(isBlockingSynchronousMethod = true)
public int getWidgetId() {
return NotePreviewConfigureActivity.appWidgetId;
}
@ReactMethod
public void setString(final String storeName, final String key, final String value) {
SharedPreferences details = getReactApplicationContext().getSharedPreferences(storeName, Context.MODE_PRIVATE);
SharedPreferences.Editor edit = details.edit();
edit.putString(key, value);
edit.apply();
}
@ReactMethod
public void removeString(final String storeName, final String key) {
SharedPreferences details = getReactApplicationContext().getSharedPreferences(storeName, Context.MODE_PRIVATE);
SharedPreferences.Editor edit = details.edit();
edit.remove(key);
edit.apply();
}
@ReactMethod
public void getString(final String storeName, final String key, Promise promise) {
SharedPreferences details = getReactApplicationContext().getSharedPreferences(storeName, Context.MODE_PRIVATE);
String value = details.getString(key, "");
promise.resolve(value.isEmpty() ? null : value);
}
@ReactMethod
public void saveAndFinish() {
NotePreviewConfigureActivity.saveAndFinish(mContext);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public WritableMap getIntent() {
WritableMap map = Arguments.createMap();
if (getCurrentActivity() != null) {
Intent intent = getCurrentActivity().getIntent();
Bundle extras = getCurrentActivity().getIntent().getExtras();
if (extras != null && intent != lastIntent) {
lastIntent = intent;
map.putString(NotePreviewWidget.OpenNoteId, extras.getString(NotePreviewWidget.OpenNoteId));
map.putString(ReminderViewsService.OpenReminderId, extras.getString(ReminderViewsService.OpenReminderId));
map.putString(ReminderWidgetProvider.NewReminder, extras.getString(ReminderWidgetProvider.NewReminder));
}
}
return map;
}
@ReactMethod
public void cancelAndFinish() {
NotePreviewConfigureActivity.activity.setResult(Activity.RESULT_CANCELED);
NotePreviewConfigureActivity.activity.finish();
}
@ReactMethod
public void getWidgetNotes(Promise promise) {
SharedPreferences pref = getReactApplicationContext().getSharedPreferences("appPreview", Context.MODE_PRIVATE);
Map<String, ?> map = pref.getAll();
WritableArray arr = Arguments.createArray();
for(Map.Entry<String,?> entry : map.entrySet()){
if (entry.getKey().equals("remindersList")) continue;
String value = (String) entry.getValue();
Gson gson = new Gson();
Note note = gson.fromJson(value, Note.class);
arr.pushString(note.getId());
}
promise.resolve(arr);
}
@ReactMethod
public void hasWidgetNote(final String noteId, Promise promise) {
SharedPreferences pref = getReactApplicationContext().getSharedPreferences("appPreview", Context.MODE_PRIVATE);
Map<String, ?> map = pref.getAll();
boolean found = false;
for(Map.Entry<String,?> entry : map.entrySet()){
String value = (String) entry.getValue();
if (value.contains(noteId)) {
found = true;
}
}
promise.resolve(found);
}
@ReactMethod
public void updateWidgetNote(final String noteId, final String data) {
SharedPreferences pref = getReactApplicationContext().getSharedPreferences("appPreview", Context.MODE_PRIVATE);
Map<String, ?> map = pref.getAll();
SharedPreferences.Editor edit = pref.edit();
ArrayList<String> ids = new ArrayList<>();
for(Map.Entry<String,?> entry : map.entrySet()) {
String value = (String) entry.getValue();
if (value.contains(noteId)) {
edit.putString(entry.getKey(), data);
ids.add(entry.getKey());
}
}
edit.apply();
for (String id: ids) {
NotePreviewWidget.updateAppWidget(mContext, AppWidgetManager.getInstance(mContext), Integer.parseInt(id));
}
}
@ReactMethod
public void updateReminderWidget() {
AppWidgetManager wm = AppWidgetManager.getInstance(mContext);
int[] ids = wm.getAppWidgetIds(ComponentName.createRelative(mContext.getPackageName(), ReminderWidgetProvider.class.getName()));
for (int id: ids) {
Log.d("Reminders", "Updating" + id);
RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.widget_reminders);
ReminderWidgetProvider.updateAppWidget(mContext, wm, id, views);
wm.notifyAppWidgetViewDataChanged(id, R.id.widget_list_view);
}
}
} }

View File

@@ -0,0 +1,100 @@
package com.streetwriters.notesnook;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.RemoteViewsService;
import android.content.Context;
import android.widget.RemoteViews;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.streetwriters.notesnook.datatypes.Reminder;
import java.util.ArrayList;
import java.util.List;
public class ReminderViewsService extends RemoteViewsService {
static String OpenReminderId = "com.streetwriters.notesnook.OpenReminderId";
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new ReminderRemoteViewsFactory(this.getApplicationContext(), intent);
}
}
class ReminderRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private Context context;
private List<Reminder> reminders;
public ReminderRemoteViewsFactory(Context context, Intent intent) {
this.context = context;
}
@Override
public void onCreate() {
// Initialize reminders list
reminders = new ArrayList<Reminder>();
}
@Override
public void onDataSetChanged() {
reminders.clear();
SharedPreferences preferences = context.getSharedPreferences("appPreview", Context.MODE_PRIVATE);
Gson gson = new Gson();
reminders = gson.fromJson(preferences.getString("remindersList","[]"), new TypeToken<List<Reminder>>(){}.getType());
}
@Override
public void onDestroy() {
reminders.clear();
}
@Override
public int getCount() {
return reminders.size();
}
@Override
public RemoteViews getViewAt(int position) {
Reminder reminder = reminders.get(position);
boolean useMiniLayout = reminder.getDescription() == null || reminder.getDescription().isEmpty();
RemoteViews views = new RemoteViews(context.getPackageName(), useMiniLayout ? R.layout.widget_reminder_layout_small : R.layout.widget_reminder_layout);
views.setTextViewText(R.id.reminder_title, reminder.getTitle());
if (!useMiniLayout) {
views.setTextViewText(R.id.reminder_description, reminder.getDescription());
}
views.setTextViewText(R.id.reminder_time, reminder.getFormattedTime());
final Intent fillInIntent = new Intent();
final Bundle extras = new Bundle();
extras.putString(ReminderViewsService.OpenReminderId, reminder.getId());
fillInIntent.putExtras(extras);
views.setOnClickFillInIntent(R.id.reminder_item_btn, fillInIntent);
return views;
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return true;
}
}

View File

@@ -0,0 +1,50 @@
package com.streetwriters.notesnook;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.widget.RemoteViews;
public class ReminderWidgetProvider extends AppWidgetProvider {
static String NewReminder = "com.streetwriters.notesnook.NewReminder";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_reminders);
updateAppWidget(context, appWidgetManager, appWidgetId, views);
}
}
private static Bundle getActivityOptionsBundle() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
ActivityOptions activityOptions = ActivityOptions.makeBasic();
activityOptions.setPendingIntentBackgroundActivityStartMode(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return activityOptions.toBundle();
} else
return null;
}
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, RemoteViews views) {
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE, getActivityOptionsBundle());
views.setPendingIntentTemplate(R.id.widget_list_view, pendingIntent);
Intent intent2 = new Intent(context, MainActivity.class);
intent2.putExtra(NewReminder, NewReminder);
PendingIntent pendingIntent2 = PendingIntent.getActivity(context, 0, intent2, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, getActivityOptionsBundle());
views.setOnClickPendingIntent(R.id.add_button, pendingIntent2);
Intent intent3 = new Intent(context, ReminderViewsService.class);
intent3.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
views.setRemoteAdapter(R.id.widget_list_view, intent3);
views.setEmptyView(R.id.widget_list_view, R.id.empty_view);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}

View File

@@ -0,0 +1,89 @@
package com.streetwriters.notesnook.datatypes;
public class BaseItem {
private String id;
private String type;
private long dateModified;
private long dateCreated;
private Boolean migrated;
private Boolean remote;
private Boolean synced;
private Boolean deleted;
/**
* @deprecated only kept here for migration purposes
*/
private Object deleteReason; // Assuming never can be represented as Object
// Getters and Setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public long getDateModified() {
return dateModified;
}
public void setDateModified(long dateModified) {
this.dateModified = dateModified;
}
public long getDateCreated() {
return dateCreated;
}
public void setDateCreated(long dateCreated) {
this.dateCreated = dateCreated;
}
public Boolean getMigrated() {
return migrated;
}
public void setMigrated(Boolean migrated) {
this.migrated = migrated;
}
public Boolean getRemote() {
return remote;
}
public void setRemote(Boolean remote) {
this.remote = remote;
}
public Boolean getSynced() {
return synced;
}
public void setSynced(Boolean synced) {
this.synced = synced;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Object getDeleteReason() {
return deleteReason;
}
public void setDeleteReason(Object deleteReason) {
this.deleteReason = deleteReason;
}
}

View File

@@ -0,0 +1,122 @@
package com.streetwriters.notesnook.datatypes;
public class Note extends BaseItem {
private String title;
private String headline;
private String contentId;
private Boolean locked;
private boolean pinned;
private boolean favorite;
private boolean localOnly;
private boolean conflicted;
private boolean readonly;
private long dateEdited;
private Object dateDeleted; // Assuming null can be represented as Object
private Object itemType; // Assuming null can be represented as Object
private Object deletedBy; // Assuming null can be represented as Object
// Getters and Setters
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getHeadline() {
return headline;
}
public void setHeadline(String headline) {
this.headline = headline;
}
public String getContentId() {
return contentId;
}
public void setContentId(String contentId) {
this.contentId = contentId;
}
public Boolean getLocked() {
return locked;
}
public void setLocked(Boolean locked) {
this.locked = locked;
}
public boolean isPinned() {
return pinned;
}
public void setPinned(boolean pinned) {
this.pinned = pinned;
}
public boolean isFavorite() {
return favorite;
}
public void setFavorite(boolean favorite) {
this.favorite = favorite;
}
public boolean isLocalOnly() {
return localOnly;
}
public void setLocalOnly(boolean localOnly) {
this.localOnly = localOnly;
}
public boolean isConflicted() {
return conflicted;
}
public void setConflicted(boolean conflicted) {
this.conflicted = conflicted;
}
public boolean isReadonly() {
return readonly;
}
public void setReadonly(boolean readonly) {
this.readonly = readonly;
}
public long getDateEdited() {
return dateEdited;
}
public void setDateEdited(long dateEdited) {
this.dateEdited = dateEdited;
}
public Object getDateDeleted() {
return dateDeleted;
}
public void setDateDeleted(Object dateDeleted) {
this.dateDeleted = dateDeleted;
}
public Object getItemType() {
return itemType;
}
public void setItemType(Object itemType) {
this.itemType = itemType;
}
public Object getDeletedBy() {
return deletedBy;
}
public void setDeletedBy(Object deletedBy) {
this.deletedBy = deletedBy;
}
}

View File

@@ -0,0 +1,135 @@
package com.streetwriters.notesnook.datatypes;
import java.util.concurrent.TimeUnit;
public class Reminder extends BaseItem {
private String title;
private String description;
private String formattedTime;
private String priority; // "silent", "vibrate", "urgent"
private long date;
private String mode; // "repeat", "once", "permanent"
private String recurringMode; // "week", "month", "day", "year"
private int[] selectedDays;
private boolean localOnly;
private boolean disabled;
private long snoozeUntil;
// Getters and Setters
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPriority() {
return priority;
}
public void setPriority(String priority) {
this.priority = priority;
}
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
public String getRecurringMode() {
return recurringMode;
}
public void setRecurringMode(String recurringMode) {
this.recurringMode = recurringMode;
}
public int[] getSelectedDays() {
return selectedDays;
}
public void setSelectedDays(int[] selectedDays) {
this.selectedDays = selectedDays;
}
public boolean isLocalOnly() {
return localOnly;
}
public void setLocalOnly(boolean localOnly) {
this.localOnly = localOnly;
}
public boolean isDisabled() {
return disabled;
}
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
public long getSnoozeUntil() {
return snoozeUntil;
}
public void setSnoozeUntil(long snoozeUntil) {
this.snoozeUntil = snoozeUntil;
}
public String getFormattedTime() {
return formattedTime;
}
public void setFormattedTime(String formattedTime) {
this.formattedTime = formattedTime;
}
public String formatTime(long timeInMillis) {
long currentTime = System.currentTimeMillis();
long diff = timeInMillis - currentTime;
if (diff < TimeUnit.MINUTES.toMillis(1)) {
return "in " + (diff / 1000) + " seconds";
} else if (diff < TimeUnit.HOURS.toMillis(1)) {
long minutes = TimeUnit.MILLISECONDS.toMinutes(diff);
return "in " + minutes + " minute" + (minutes > 1 ? "s" : "");
} else if (diff < TimeUnit.DAYS.toMillis(1)) {
long hours = TimeUnit.MILLISECONDS.toHours(diff);
return "in " + hours + " hour" + (hours > 1 ? "s" : "");
} else if (diff < TimeUnit.DAYS.toMillis(2)) {
return "tomorrow";
} else if (diff < TimeUnit.DAYS.toMillis(7)) {
long days = TimeUnit.MILLISECONDS.toDays(diff);
return "in " + days + " day" + (days > 1 ? "s" : "");
} else if (diff < TimeUnit.DAYS.toMillis(30)) {
long weeks = TimeUnit.MILLISECONDS.toDays(diff) / 7;
return "in " + weeks + " week" + (weeks > 1 ? "s" : "");
} else if (diff < TimeUnit.DAYS.toMillis(365)) {
long months = TimeUnit.MILLISECONDS.toDays(diff) / 30;
return "in " + months + " month" + (months > 1 ? "s" : "");
} else {
long years = TimeUnit.MILLISECONDS.toDays(diff) / 365;
return "in " + years + " year" + (years > 1 ? "s" : "");
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -0,0 +1,37 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:padding="10dp"
android:theme="@style/ThemeOverlay.Notesnook.AppWidgetContainer">
<LinearLayout
android:layout_width="match_parent"
android:id="@+id/widget_button"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/layout_bg"
android:paddingHorizontal="10dp"
android:elevation="5dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@drawable/add_note"
android:contentDescription="New note icon" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:textColor="@color/text"
android:textSize="16sp"
android:text="@string/take_a_quick_note" />
</LinearLayout>
</RelativeLayout>

View File

@@ -3,35 +3,39 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@android:color/transparent" android:background="@android:color/transparent"
android:padding="@dimen/widget_margin" android:padding="10dp"
android:theme="@style/ThemeOverlay.Notesnook.AppWidgetContainer"> android:theme="@style/ThemeOverlay.Notesnook.AppWidgetContainer">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:id="@+id/widget_button" android:id="@+id/widget_button"
android:layout_height="50dp" android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:background="@drawable/layout_bg" android:background="@drawable/layout_bg"
android:paddingHorizontal="10dp" android:paddingHorizontal="10dp"
android:paddingVertical="10dp"
android:elevation="5dp" android:elevation="5dp"
android:orientation="horizontal"> android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@drawable/add_note"
android:contentDescription="New note icon" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp" android:layout_marginLeft="8dp"
android:id="@+id/widget_title"
android:textColor="@color/text" android:textColor="@color/text"
android:textSize="16sp" android:textSize="16sp"
android:text="@string/take_a_quick_note" /> android:textStyle="bold"
android:text="Widget unconfigured" />
<TextView
android:id="@+id/widget_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:textColor="@color/text"
android:textSize="14sp"
android:text="Configure this widget to show a note here." />
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>

View File

@@ -0,0 +1,8 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="No upcoming reminders"
android:textSize="16sp"
android:textColor="@android:color/darker_gray"
android:gravity="center" />

View File

@@ -0,0 +1,28 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/reminder_item_btn">
<TextView
android:id="@+id/reminder_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/text"
android:textSize="16sp" />
<TextView
android:id="@+id/reminder_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/text"
android:textSize="14sp" />
<TextView
android:id="@+id/reminder_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textColor="@color/text" />
</LinearLayout>

View File

@@ -0,0 +1,21 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/reminder_item_btn">
<TextView
android:id="@+id/reminder_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/text"
android:textSize="16sp" />
<TextView
android:id="@+id/reminder_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textColor="@color/text" />
</LinearLayout>

View File

@@ -0,0 +1,64 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/layout_bg"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="12dp"
android:layout_gravity="center"
android:paddingTop="12dp"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="2dp"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/text"
android:text="Upcoming Reminders"/>
<ImageButton
android:layout_width="30dp"
android:id="@+id/add_button"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:background="@drawable/ic_newnote" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="8dp"
android:background="@color/border" />
<ListView
android:id="@+id/widget_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@color/border"
android:paddingBottom="12dp"
android:paddingHorizontal="12dp"
android:dividerHeight="1dp" />
<LinearLayout
android:id="@+id/empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAlignment="center"
android:gravity="center"
android:text="Tap on + to add reminder"/>
</LinearLayout>
</LinearLayout>

View File

@@ -6,5 +6,6 @@
<color name="light_blue_900">#FF01579B</color> <color name="light_blue_900">#FF01579B</color>
<color name="bootsplash_background">#1f1f1f</color> <color name="bootsplash_background">#1f1f1f</color>
<color name="background">#1D1D1D</color> <color name="background">#1D1D1D</color>
<color name="border">#2E2E2E</color>
<color name="text">#B4B4B4</color> <color name="text">#B4B4B4</color>
</resources> </resources>

View File

@@ -5,6 +5,7 @@
<color name="light_blue_600">#FF039BE5</color> <color name="light_blue_600">#FF039BE5</color>
<color name="light_blue_900">#FF01579B</color> <color name="light_blue_900">#FF01579B</color>
<color name="bootsplash_background">#FFFFFF</color> <color name="bootsplash_background">#FFFFFF</color>
<color name="background">#FFFFFF</color> <color name="background">#D8000000</color>
<color name="text">#000000</color> <color name="border">#CCCCCC</color>
<color name="text">#1D1D1D</color>
</resources> </resources>

View File

@@ -4,4 +4,9 @@
<string name="appwidget_text">EXAMPLE</string> <string name="appwidget_text">EXAMPLE</string>
<string name="add_widget">Add widget</string> <string name="add_widget">Add widget</string>
<string name="take_a_quick_note">Take a quick note.</string> <string name="take_a_quick_note">Take a quick note.</string>
<string name="reminders">Quick overview of upcoming reminders</string>
<string name="reminders_title">Reminders</string>
<string name="note">Note</string>
<string name="note_description">Add a note to home screen</string>
<string name="quick_note">Quick note</string>
</resources> </resources>

View File

@@ -1,9 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="@layout/note_widget" android:initialKeyguardLayout="@layout/new_note_widget"
android:initialLayout="@layout/note_widget" android:initialLayout="@layout/new_note_widget"
android:minWidth="50dp" android:minWidth="400dp"
android:minHeight="50dp" android:minHeight="50dp"
android:minResizeWidth="50dp"
android:minResizeHeight="50dp"
android:description="@string/take_a_quick_note"
android:targetCellWidth="5"
android:targetCellHeight="1"
android:previewImage="@drawable/widget_preview" android:previewImage="@drawable/widget_preview"
android:resizeMode="horizontal|vertical" android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000" android:updatePeriodMillis="86400000"

View File

@@ -2,11 +2,16 @@
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="@layout/note_widget" android:initialKeyguardLayout="@layout/note_widget"
android:initialLayout="@layout/note_widget" android:initialLayout="@layout/note_widget"
android:minWidth="50dp" android:configure="com.streetwriters.notesnook.NotePreviewConfigureActivity"
android:widgetFeatures="reconfigurable"
android:minResizeWidth="100dp"
android:minResizeHeight="50dp"
android:minWidth="400dp"
android:description="@string/note_description"
android:minHeight="50dp" android:minHeight="50dp"
android:targetCellWidth="5" android:targetCellWidth="5"
android:targetCellHeight="1" android:targetCellHeight="1"
android:previewImage="@drawable/widget_preview" android:previewImage="@drawable/note_widget_preview"
android:resizeMode="horizontal|vertical" android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000" android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen"/> android:widgetCategory="home_screen"/>

View File

@@ -0,0 +1,14 @@
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_reminders"
android:minWidth="400dp"
android:minHeight="100dp"
android:minResizeWidth="400dp"
android:minResizeHeight="50dp"
android:description="@string/reminders"
android:targetCellWidth="5"
android:targetCellHeight="2"
android:resizeMode="horizontal|vertical"
android:previewImage="@drawable/reminder_preview"
android:updatePeriodMillis="1024"
android:widgetCategory="home_screen"
/>

Some files were not shown because too many files have changed in this diff Show More