diff --git a/agent.md b/agent.md new file mode 100644 index 000000000..1c0b29b8d --- /dev/null +++ b/agent.md @@ -0,0 +1,51 @@ +## Notesnook Design Agent + +### Purpose + +- Implement Figma designs from user-provided links into the Notesnook app with high visual fidelity. +- Use related components and files provided by the user as the source of truth for local patterns. +- Preserve behavior, navigation, and existing data flow while updating UI. + +### When To Use This Agent + +- Use this agent when the task is design-to-code for app UI. +- Prefer this agent over a general coding agent when the user provides a Figma link and asks for redesign implementation. + +### Scope + +- Primary focus: apps/mobile. +- Secondary scope: shared UI dependencies needed for the design update (tokens, icons, strings, and generated assets). +- Do not perform unrelated refactors. + +### Tool Preferences + +- Prefer Figma design-context tools to extract layout, spacing rhythm, typography intent, and asset references from the exact node. +- Prefer direct workspace edits and targeted validation for touched files. +- Avoid introducing new UI frameworks or web-specific styling approaches. + +### Repo Conventions + +- Use theme and token systems first: useThemeColors, spacing/radius constants, and shared typography primitives. +- Reuse existing UI primitives and patterns before creating new abstractions. +- Keep dark and light mode compatibility by default. +- Keep changes minimal, isolated, and review-friendly. + +### Icon Conventions + +- Add new icon SVGs to packages/icons/svgs with lowercase kebab-case names. +- Regenerate icon assets from apps/mobile using npx react-native-nano-icons. +- Use generated icon names through AppIcon with icon family notesnook where applicable. + +### Figma To Code Workflow + +1. Read the exact Figma node from the provided link. +2. Compare against existing repo patterns and referenced components. +3. Implement with React Native conventions already used in the app. +4. Preserve behavior and interactions unless explicitly changed. +5. Validate compile and lint state for edited files. + +### Output Expectations + +- Provide a concise summary of what changed. +- List modified files and any generated artifacts. +- Call out follow-up steps only when needed. diff --git a/apps/mobile/app/app.tsx b/apps/mobile/app/app.tsx index 44fd2eb0d..6cea1958a 100644 --- a/apps/mobile/app/app.tsx +++ b/apps/mobile/app/app.tsx @@ -35,7 +35,7 @@ import { Toast } from "./components/toast"; import { useAppEvents } from "./hooks/use-app-events"; import { NotePreviewConfigure } from "./screens/note-preview-configure"; import { RootNavigation } from "./navigation/navigation-stack"; -import { themeTrpcClient } from "./screens/settings/theme-selector"; +import { themeTrpcClient } from "./screens/settings/components/theme-selector"; import Notifications from "./services/notifications"; import SettingsService from "./services/settings"; import { TipManager } from "./services/tip-manager"; diff --git a/apps/mobile/app/components/app-lock/index.tsx b/apps/mobile/app/components/app-lock/index.tsx index bcab38b15..183c8340f 100644 --- a/apps/mobile/app/components/app-lock/index.tsx +++ b/apps/mobile/app/components/app-lock/index.tsx @@ -55,6 +55,7 @@ import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view import { strings } from "@notesnook/intl"; import { editorController } from "../../screens/editor/tiptap/utils"; import { useTabStore } from "../../screens/editor/tiptap/use-tab-store"; +import { PASSWORD_PLACEHOLDER } from "../../utils/constants"; const getUser = () => { const user = MMKV.getString("user"); @@ -96,9 +97,6 @@ const AppLocked = () => { const lastAppState = useRef(appState); const biometricUnlockAwaitingUserInput = useRef(false); const { height } = useWindowDimensions(); - const keyboardType = useSettingStore( - (state) => state.settings.applockKeyboardType - ); const appLockHasPasswordSecurity = useSettingStore( (state) => state.settings.appLockHasPasswordSecurity ); @@ -157,8 +155,7 @@ const AppLocked = () => { if (!appLockHasPasswordSecurity) { await setAppLockVerificationCipher(password.current); SettingsService.set({ - appLockHasPasswordSecurity: true, - applockKeyboardType: "default" + appLockHasPasswordSecurity: true }); DatabaseLogger.info("App lock migrated to password security"); } @@ -167,7 +164,7 @@ const AppLocked = () => { password.current = undefined; } else { ToastManager.show({ - heading: strings.invalid(keyboardType), + heading: strings.invalid("password"), type: "error", context: "local" }); @@ -290,9 +287,7 @@ const AppLocked = () => { { if ( !biometricsAuthEnabled || @@ -303,13 +298,7 @@ const AppLocked = () => { }, 32); } }} - placeholder={ - appLockHasPasswordSecurity - ? keyboardType === "numeric" - ? strings.enterApplockPassword() - : strings.enterApplockPin() - : strings.enterAccountPassword() - } + placeholder={PASSWORD_PLACEHOLDER} onChangeText={(v) => (password.current = v)} onSubmit={() => { onSubmit(); diff --git a/apps/mobile/app/components/attachments/index.tsx b/apps/mobile/app/components/attachments/index.tsx index b5b7b6943..cd4da9d02 100644 --- a/apps/mobile/app/components/attachments/index.tsx +++ b/apps/mobile/app/components/attachments/index.tsx @@ -34,7 +34,7 @@ import create from "zustand"; import { db } from "../../common/database"; import filesystem from "../../common/filesystem"; import { downloadAttachments } from "../../common/filesystem/download-attachment"; -import { AttachmentGroupProgress } from "../../screens/settings/attachment-group-progress"; +import { AttachmentGroupProgress } from "../../screens/settings/components/attachment-group-progress"; import { presentSheet, ToastManager } from "../../services/event-manager"; import { useAttachmentStore } from "../../stores/use-attachment-store"; import { AppFontSize } from "../../utils/size"; diff --git a/apps/mobile/app/components/auth/change-password.tsx b/apps/mobile/app/components/auth/change-password.tsx index d10ae1341..739cc155f 100644 --- a/apps/mobile/app/components/auth/change-password.tsx +++ b/apps/mobile/app/components/auth/change-password.tsx @@ -23,10 +23,9 @@ import React, { useRef, useState } from "react"; import { View } from "react-native"; import { db } from "../../common/database"; import BackupService from "../../services/backup"; -import { eSendEvent, ToastManager } from "../../services/event-manager"; +import { ToastManager } from "../../services/event-manager"; import Navigation from "../../services/navigation"; import { useUserStore } from "../../stores/use-user-store"; -import { eOpenRecoveryKeyDialog } from "../../utils/events"; import { AppFontSize } from "../../utils/size"; import { DefaultAppStyles } from "../../utils/styles"; import { Dialog } from "../dialog"; @@ -36,6 +35,8 @@ import FormInput, { createFormRef, validators } from "../ui/input/form-input"; import { Notice } from "../ui/notice"; import Paragraph from "../ui/typography/paragraph"; import { TextInput } from "react-native-gesture-handler"; +import { Spacing } from "../../common/design/spacing"; +import RecoveryKeySheet from "../sheets/recovery-key"; export const ChangePassword = () => { const { colors } = useThemeColors(); @@ -92,7 +93,7 @@ export const ChangePassword = () => { }); setLoading(false); Navigation.goBack(); - eSendEvent(eOpenRecoveryKeyDialog); + RecoveryKeySheet.present(); } catch (e) { const message = (e as Error).message; setLoading(false); @@ -109,12 +110,15 @@ export const ChangePassword = () => { { autoComplete="password" autoCapitalize="none" autoCorrect={false} - placeholder={strings.currentPassword()} + placeholder={"•••••••••"} onSubmitEditing={() => { passwordInputRef.current?.focus(); }} @@ -133,6 +137,7 @@ export const ChangePassword = () => { { autoComplete="password" autoCapitalize="none" autoCorrect={false} - placeholder={strings.newPassword()} + placeholder={"•••••••••"} + onSubmitEditing={() => { + changePassword(); + }} + /> + + { changePassword(); }} @@ -168,15 +194,14 @@ export const ChangePassword = () => { ) : null} - - - - - +