From b77254a045e4e466546bd414530133c8b9e99575 Mon Sep 17 00:00:00 2001 From: ammarahm-ed Date: Wed, 4 Jan 2023 19:13:09 +0500 Subject: [PATCH] mobile: configurable snooze time --- .../app/components/sheets/reminder/index.tsx | 3 +- .../app/screens/settings/section-item.tsx | 37 ++++++++++++++++--- .../app/screens/settings/settings-data.tsx | 19 +++++++++- apps/mobile/app/screens/settings/types.ts | 4 +- apps/mobile/app/services/notifications.ts | 11 ++++-- apps/mobile/app/stores/use-reminder-store.ts | 29 ++++----------- apps/mobile/app/stores/use-setting-store.ts | 4 +- packages/core/utils/grouping.js | 2 +- 8 files changed, 74 insertions(+), 35 deletions(-) diff --git a/apps/mobile/app/components/sheets/reminder/index.tsx b/apps/mobile/app/components/sheets/reminder/index.tsx index 1e5690e4e..cb570ee67 100644 --- a/apps/mobile/app/components/sheets/reminder/index.tsx +++ b/apps/mobile/app/components/sheets/reminder/index.tsx @@ -188,7 +188,8 @@ export default function ReminderSheet({ mode: reminderMode, localOnly: reminderMode === "permanent", snoozeUntil: - date?.getTime() > Date.now() ? undefined : reminder?.snoozeUntil + date?.getTime() > Date.now() ? undefined : reminder?.snoozeUntil, + disabled: false }); const _reminder = db.reminders?.reminder(reminderId); diff --git a/apps/mobile/app/screens/settings/section-item.tsx b/apps/mobile/app/screens/settings/section-item.tsx index 92dfa4a1d..8d69635a2 100644 --- a/apps/mobile/app/screens/settings/section-item.tsx +++ b/apps/mobile/app/screens/settings/section-item.tsx @@ -22,16 +22,17 @@ import { StackActions, useNavigation } from "@react-navigation/native"; -import React from "react"; -import { View } from "react-native"; +import React, { useRef } from "react"; +import { View, TextInput } from "react-native"; import Icon from "react-native-vector-icons/MaterialCommunityIcons"; import ToggleSwitch from "toggle-switch-react-native"; +import Input from "../../components/ui/input"; import { PressableButton } from "../../components/ui/pressable"; import Seperator from "../../components/ui/seperator"; import Paragraph from "../../components/ui/typography/paragraph"; import SettingsService from "../../services/settings"; import useNavigationStore from "../../stores/use-navigation-store"; -import { useSettingStore } from "../../stores/use-setting-store"; +import { SettingStore, useSettingStore } from "../../stores/use-setting-store"; import { useThemeStore } from "../../stores/use-theme-store"; import { SIZE } from "../../utils/size"; import { components } from "./components"; @@ -43,6 +44,8 @@ const _SectionItem = ({ item }: { item: SettingSection }) => { const navigation = useNavigation>(); const current = item.useHook && item.useHook(item); const isHidden = item.hidden && item.hidden(item.property || current); + const inputRef = useRef(null); + const onChangeSettings = () => { if (item.modifer) { item.modifer(item.property || current); @@ -61,7 +64,6 @@ const _SectionItem = ({ item }: { item: SettingSection }) => { backgroundColor: colors.errorBg } : {}; - return isHidden ? null : ( { flexDirection: "row", justifyContent: "space-between", paddingVertical: 20, - borderRadius:0, + borderRadius: 0, ...styles }} onPress={() => { @@ -155,6 +157,31 @@ const _SectionItem = ({ item }: { item: SettingSection }) => { {components[item.component]} )} + + {item.type === "input" && ( + { + if (e.nativeEvent.text) { + SettingsService.set({ + [item.property as string]: e.nativeEvent.text + }); + } + item.inputProperties?.onSubmitEditing?.(e); + }} + containerStyle={{ marginTop: 12 }} + fwdRef={inputRef} + onLayout={() => { + inputRef?.current?.setNativeProps({ + text: + SettingsService.get()[ + item.property as keyof SettingStore["settings"] + ] + "" + }); + }} + defaultValue={item.inputProperties?.defaultValue} + /> + )} diff --git a/apps/mobile/app/screens/settings/settings-data.tsx b/apps/mobile/app/screens/settings/settings-data.tsx index ac40b0178..d6d7118fc 100644 --- a/apps/mobile/app/screens/settings/settings-data.tsx +++ b/apps/mobile/app/screens/settings/settings-data.tsx @@ -833,7 +833,24 @@ export const settingsGroups: SettingSection[] = [ } }, description: - "Disable reminder notifications on this device, this is useful when you have notesnook on multiple devices & want to recieve reminder notifications only on your primary device." + "Disable reminder notifications on this device, this is useful when you have Notesnook on multiple devices & want to recieve reminder notifications only on your primary device." + }, + { + id: "snooze-time", + property: "defaultSnoozeTime", + type: "input", + icon: "snooze", + name: "Default snooze time", + description: + "Set the default time to snooze a reminder to when you press the snooze button on a notification", + inputProperties: { + keyboardType: "decimal-pad", + defaultValue: 5 + "", + placeholder: "Set snooze time in minutes", + onSubmitEditing:() => { + Notifications.setupReminders(); + } + } } ] } diff --git a/apps/mobile/app/screens/settings/types.ts b/apps/mobile/app/screens/settings/types.ts index 6464ca1d6..c0ab9d2bf 100644 --- a/apps/mobile/app/screens/settings/types.ts +++ b/apps/mobile/app/screens/settings/types.ts @@ -17,11 +17,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +import { TextInput } from "react-native"; import { Settings } from "../../stores/use-setting-store"; export type SettingSection = { id: string; - type?: "screen" | "switch" | "component" | "danger"; + type?: "screen" | "switch" | "component" | "danger" | "input"; name?: string | ((current?: unknown) => string); description?: string | ((current: unknown) => string); icon?: string; @@ -33,6 +34,7 @@ export type SettingSection = { useHook?: (...args: unknown[]) => unknown; hidden?: (current: unknown) => boolean; onChange?: (property: boolean) => void; + inputProperties?: TextInput["props"]; }; export type SettingsGroup = { diff --git a/apps/mobile/app/services/notifications.ts b/apps/mobile/app/services/notifications.ts index bb851912c..ea43f396d 100644 --- a/apps/mobile/app/services/notifications.ts +++ b/apps/mobile/app/services/notifications.ts @@ -128,9 +128,12 @@ const onEvent = async ({ type, detail }: Event) => { const reminder = db.reminders?.reminder( notification?.id?.split("_")[0] ); + const reminderTime = parseInt( + SettingsService.get().defaultSnoozeTime || "5" + ); await db.reminders?.add({ ...reminder, - snoozeUntil: Date.now() + 10 * 60000 + snoozeUntil: Date.now() + reminderTime * 60000 }); await Notifications.scheduleNotification( db.reminders?.reminder(reminder?.id) @@ -186,6 +189,7 @@ async function setupIOSCategories() { try { if (Platform.OS === "ios") { const categories = await notifee.getNotificationCategories(); + const reminderTime = SettingsService.get().defaultSnoozeTime; if (categories.findIndex((c) => c.id === "REMINDER") === -1) { await notifee.setNotificationCategories([ { @@ -205,7 +209,7 @@ async function setupIOSCategories() { { id: "REMINDER_SNOOZE", foreground: false, - title: "Remind in 10 min", + title: `Remind in ${reminderTime} min`, authenticationRequired: false }, { @@ -254,9 +258,10 @@ async function scheduleNotification( iosProperties["sound"] = "default"; } + const reminderTime = SettingsService.get().defaultSnoozeTime; const androidActions = [ { - title: "Remind in 10 min", + title: `Remind in ${reminderTime} min`, pressAction: { id: "REMINDER_SNOOZE" } diff --git a/apps/mobile/app/stores/use-reminder-store.ts b/apps/mobile/app/stores/use-reminder-store.ts index 97ad24efd..d189cc5cc 100644 --- a/apps/mobile/app/stores/use-reminder-store.ts +++ b/apps/mobile/app/stores/use-reminder-store.ts @@ -17,38 +17,23 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { groupArray } from "@notesnook/core/utils/grouping"; +import { groupReminders } from "@notesnook/core/utils/grouping"; import create, { State } from "zustand"; import { db } from "../common/database"; import { Reminder } from "../services/notifications"; export interface ReminderStore extends State { - reminders: Reminder[]; + reminders: (Reminder | { title: string; type: "header" })[]; setReminders: (items?: Reminder[]) => void; cleareReminders: () => void; } -export const useReminderStore = create((set, get) => ({ +export const useReminderStore = create((set) => ({ reminders: [], - setReminders: (items) => { - if (!items) { - set({ - reminders: groupArray( - (db.reminders?.all as Reminder[]) || [], - db.settings?.getGroupOptions("reminders") - ) - }); - return; - } - const prev = get().reminders; - for (let i = 0; i < items.length; i++) { - const item = items[i]; - const index = prev.findIndex((v) => v.id === item.id); - if (index !== -1) { - prev[index] = item; - } - } - set({ reminders: prev }); + setReminders: () => { + set({ + reminders: groupReminders((db.reminders?.all as Reminder[]) || []) + }); }, cleareReminders: () => set({ reminders: [] }) })); diff --git a/apps/mobile/app/stores/use-setting-store.ts b/apps/mobile/app/stores/use-setting-store.ts index 23f2b2c92..c51aa3c39 100644 --- a/apps/mobile/app/stores/use-setting-store.ts +++ b/apps/mobile/app/stores/use-setting-store.ts @@ -66,6 +66,7 @@ export type Settings = { disableAutoSync?: boolean; disableSync?: boolean; disableReminderNotifications?: boolean; + defaultSnoozeTime?: string; }; type DimensionsType = { @@ -138,7 +139,8 @@ export const useSettingStore = create((set) => ({ sessionExpired: false, version: null, doubleSpacedLines: true, - disableReminderNotifications: false + disableReminderNotifications: false, + defaultSnoozeTime: "5" }, sheetKeyboardHandler: true, fullscreen: false, diff --git a/packages/core/utils/grouping.js b/packages/core/utils/grouping.js index c15ad170c..b0d10d7d8 100644 --- a/packages/core/utils/grouping.js +++ b/packages/core/utils/grouping.js @@ -138,7 +138,7 @@ export function groupArray( /** * @param {any[]} array * @param {GroupOptions} options - * @returns Grouped array + * @returns {(Reminder | {type: "header", title: string})[]} Grouped array */ export function groupReminders(array) { const groups = new Map([