diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3b35cff..6c54e01 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,13 +9,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Use Node.js 20 - uses: actions/setup-node@v4 - with: - node-version: 20.x - cache: 'npm' - - name: Install dependencies - run: npm i - - run: npm run build - - run: npm run lint:ci + - uses: actions/checkout@v4 + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20.x + cache: 'npm' + - name: Install dependencies + run: npm i + - run: npm run build + - run: npm run lint:ci diff --git a/AUTOMATED_RELEASE.md b/AUTOMATED_RELEASE.md index 7ed5329..31f017f 100644 --- a/AUTOMATED_RELEASE.md +++ b/AUTOMATED_RELEASE.md @@ -12,15 +12,16 @@ Builds and (optionally) uploads signed Android and iOS release artifacts from th Common flags on `release.sh`: -| Flag | Effect | -|---|---| -| `--android` / `--ios` | Build only one platform | -| `--bump minor\|major` | Bump type (default: `patch`) | -| `--skip-bump` | Build with the current version, don't bump | -| `--upload` | Upload after building | -| `--track TRACK` | Play Store track for `--upload` (default: `internal`) | +| Flag | Effect | +| --------------------- | ----------------------------------------------------- | +| `--android` / `--ios` | Build only one platform | +| `--bump minor\|major` | Bump type (default: `patch`) | +| `--skip-bump` | Build with the current version, don't bump | +| `--upload` | Upload after building | +| `--track TRACK` | Play Store track for `--upload` (default: `internal`) | Outputs: + - Android: `android/app/build/outputs/bundle/release/app-release.aab` - iOS: `build/ios/Donetick.ipa` @@ -36,15 +37,15 @@ Outputs: All secrets live in Vaultwarden (`https://www.bitwarden.com`) as Secure Notes, named exactly as below: -| Vault item name | Written to | Encoding | -|---|---|---| -| Donetick Google Services Android | `android/app/google-services.json` | raw | -| Donetick Android Keystore | `android/app/release/donetick.jks` | base64 | -| Donetick Keystore Password | (used inline for `android/keystore.properties`) | raw | -| Donetick Google Play Service Account | `android/play-service-account.json` | raw | -| Donetick Google Services iOS | `ios/App/App/GoogleService-Info.plist` | raw | -| Donetick App Store Connect Key | `ios/AuthKey_84F695CDQ3.p8` | base64 | -| Donetick Env Production | `.env.production` | raw | +| Vault item name | Written to | Encoding | +| ------------------------------------ | ----------------------------------------------- | -------- | +| Donetick Google Services Android | `android/app/google-services.json` | raw | +| Donetick Android Keystore | `android/app/release/donetick.jks` | base64 | +| Donetick Keystore Password | (used inline for `android/keystore.properties`) | raw | +| Donetick Google Play Service Account | `android/play-service-account.json` | raw | +| Donetick Google Services iOS | `ios/App/App/GoogleService-Info.plist` | raw | +| Donetick App Store Connect Key | `ios/AuthKey_84F695CDQ3.p8` | base64 | +| Donetick Env Production | `.env.production` | raw | None of these files are committed to git — all covered by `.gitignore`. @@ -57,6 +58,7 @@ The App target uses **manual signing for Release**, not Automatic. This was a de - `fastlane/Fastfile`'s `ios release` lane passes explicit `export_options: { signingStyle: "manual", provisioningProfiles: {...} }` to `build_app` — do **not** switch this back to `-allowProvisioningUpdates`/automatic without a good reason, it re-triggers the ambiguous cert selection. **If you ever add/change an entitlement** (new Capability in Signing & Capabilities, e.g. a new permission), the existing provisioning profile becomes stale and exports will fail with an error like `"App.app" requires a provisioning profile with the X feature`. Fix: + 1. developer.apple.com → Identifiers → `com.donetick.app` → confirm the new capability is checked 2. developer.apple.com → Profiles → find `Donetick App Store(fastline)` → regenerate it → download 3. Install it locally: get its UUID (`security cms -D -i .mobileprovision | plutil -extract UUID xml1 -o - -`) and copy to `~/Library/MobileDevice/Provisioning Profiles/.mobileprovision` diff --git a/android/app/release/output-metadata.json b/android/app/release/output-metadata.json index 2b10993..c6dd734 100644 --- a/android/app/release/output-metadata.json +++ b/android/app/release/output-metadata.json @@ -21,17 +21,13 @@ { "minApi": 28, "maxApi": 30, - "baselineProfiles": [ - "baselineProfiles/1/app-release.dm" - ] + "baselineProfiles": ["baselineProfiles/1/app-release.dm"] }, { "minApi": 31, "maxApi": 2147483647, - "baselineProfiles": [ - "baselineProfiles/0/app-release.dm" - ] + "baselineProfiles": ["baselineProfiles/0/app-release.dm"] } ], "minSdkVersionForDexing": 28 -} \ No newline at end of file +} diff --git a/android/app/src/main/res/.impeccable/hook.cache.json b/android/app/src/main/res/.impeccable/hook.cache.json index ebc7c5d..9f68402 100644 --- a/android/app/src/main/res/.impeccable/hook.cache.json +++ b/android/app/src/main/res/.impeccable/hook.cache.json @@ -1 +1 @@ -{"version":1,"sessions":{}} \ No newline at end of file +{ "version": 1, "sessions": {} } diff --git a/crowdin.yml b/crowdin.yml index 7cea3f7..5665ddc 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,7 +1,7 @@ # Crowdin configuration for Donetick # See: https://support.crowdin.com/configuration-file/ -project_id: "donetick" +project_id: 'donetick' api_token_env: CROWDIN_API_TOKEN preserve_hierarchy: true diff --git a/fastlane/README.md b/fastlane/README.md index e93f221..8f40103 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -31,8 +31,7 @@ Build a signed, App Store-ready .ipa Upload the built .ipa to TestFlight ----- - +--- ## Android @@ -60,7 +59,7 @@ Build a signed release .apk (for sideloading/testing) Upload the built .aab to the Play Store (internal testing track by default) ----- +--- This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. diff --git a/ionic.config.json b/ionic.config.json index a61dc93..087d13b 100644 --- a/ionic.config.json +++ b/ionic.config.json @@ -4,4 +4,4 @@ "capacitor": {} }, "type": "custom" -} \ No newline at end of file +} diff --git a/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json index b1a8483..5e294d5 100644 --- a/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -11,4 +11,4 @@ "author": "xcode", "version": 1 } -} \ No newline at end of file +} diff --git a/ios/App/App/Assets.xcassets/Contents.json b/ios/App/App/Assets.xcassets/Contents.json index da4a164..97a8662 100644 --- a/ios/App/App/Assets.xcassets/Contents.json +++ b/ios/App/App/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } -} \ No newline at end of file +} diff --git a/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json b/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json index 84a416d..57ba80d 100644 --- a/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json +++ b/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json @@ -53,4 +53,4 @@ "version": 1, "author": "xcode" } -} \ No newline at end of file +} diff --git a/public/.well-known/apple-app-site-association.json b/public/.well-known/apple-app-site-association.json index 70aab72..6e2da30 100644 --- a/public/.well-known/apple-app-site-association.json +++ b/public/.well-known/apple-app-site-association.json @@ -8,4 +8,4 @@ } ] } -} \ No newline at end of file +} diff --git a/public/locales/he/settings.json b/public/locales/he/settings.json index f2262f8..fa8e1d1 100644 --- a/public/locales/he/settings.json +++ b/public/locales/he/settings.json @@ -492,4 +492,3 @@ } } } - diff --git a/public/locales/zh-CN/chores.json b/public/locales/zh-CN/chores.json index 3f966f1..60ddfe1 100644 --- a/public/locales/zh-CN/chores.json +++ b/public/locales/zh-CN/chores.json @@ -72,4 +72,4 @@ "delete": "删除会话" } } -} \ No newline at end of file +} diff --git a/src/i18n/README.md b/src/i18n/README.md index c4c3e30..a723f9e 100644 --- a/src/i18n/README.md +++ b/src/i18n/README.md @@ -28,7 +28,7 @@ import { useTranslation } from 'react-i18next' function MyComponent() { const { t } = useTranslation('settings') // or 'common', 'chores' - + return

{t('title')}

} ``` @@ -40,9 +40,9 @@ import { useLocalization } from '@/contexts/LocalizationContext' function MyComponent() { const { formatDate, formatDateTime, formatRelative } = useLocalization() - + const date = new Date() - + return (

Date: {formatDate(date)}

@@ -59,19 +59,10 @@ function MyComponent() { import { useLocalization } from '@/contexts/LocalizationContext' function MyComponent() { - const { - language, - setLanguage, - dateFormat, - setDateFormat, - isRTL - } = useLocalization() - - return ( -
- Current language: {language} -
- ) + const { language, setLanguage, dateFormat, setDateFormat, isRTL } = + useLocalization() + + return
Current language: {language}
} ``` @@ -90,6 +81,7 @@ function MyComponent() { ## RTL Support Languages in the `RTL_LANGUAGES` array automatically get: + - `dir="rtl"` on the document - RTL-specific CSS styles - Proper text alignment @@ -99,6 +91,7 @@ Currently supported RTL languages: Arabic (ar), Hebrew (he), Persian (fa), Urdu ## Date Format Preferences Users can choose from: + - MM/DD/YYYY (US) - DD/MM/YYYY (Europe) - YYYY-MM-DD (ISO) @@ -113,5 +106,6 @@ Users can choose from: ## First Day of Week Users can choose: + - Sunday - Monday diff --git a/src/index.css b/src/index.css index a00da6d..2e47587 100644 --- a/src/index.css +++ b/src/index.css @@ -30,8 +30,6 @@ html { border-radius: 4px; } - - /* Prevent iOS Safari from auto-zooming on input focus (triggered when font-size < 16px) */ @supports (-webkit-touch-callout: none) { input, diff --git a/src/styles/safe-area.css b/src/styles/safe-area.css index bc3eece..87542ce 100644 --- a/src/styles/safe-area.css +++ b/src/styles/safe-area.css @@ -82,11 +82,15 @@ /* Height utilities that account for safe areas */ .min-h-screen-safe { - min-height: calc(100vh - var(--safe-area-inset-top) - var(--safe-area-inset-bottom)); + min-height: calc( + 100vh - var(--safe-area-inset-top) - var(--safe-area-inset-bottom) + ); } .h-screen-safe { - height: calc(100vh - var(--safe-area-inset-top) - var(--safe-area-inset-bottom)); + height: calc( + 100vh - var(--safe-area-inset-top) - var(--safe-area-inset-bottom) + ); } /* Top positioning that accounts for safe area */ diff --git a/src/views/components/RichTextEditor.css b/src/views/components/RichTextEditor.css index 042bf74..2d5d547 100644 --- a/src/views/components/RichTextEditor.css +++ b/src/views/components/RichTextEditor.css @@ -57,11 +57,14 @@ border-radius: 10px; overflow: hidden; background-color: var(--joy-palette-neutral-softBg, #f0f4f8); - transition: box-shadow 0.15s ease, background-color 0.15s ease; + transition: + box-shadow 0.15s ease, + background-color 0.15s ease; } .quill-root:focus-within { - box-shadow: 0 0 0 1px var(--joy-palette-primary-outlinedBorder, rgba(11, 107, 203, 0.15)); + box-shadow: 0 0 0 1px + var(--joy-palette-primary-outlinedBorder, rgba(11, 107, 203, 0.15)); } .quill-root:hover:not(:focus-within) { @@ -70,7 +73,8 @@ .quill-root .ql-toolbar.ql-snow { border: none; - border-bottom: 1px solid var(--joy-palette-neutral-softActiveBg, rgba(99, 107, 116, 0.16)); + border-bottom: 1px solid + var(--joy-palette-neutral-softActiveBg, rgba(99, 107, 116, 0.16)); border-radius: 0; background: transparent; box-shadow: none; diff --git a/src/views/components/SmartTaskTitleInput.css b/src/views/components/SmartTaskTitleInput.css index 02b4333..1283f48 100644 --- a/src/views/components/SmartTaskTitleInput.css +++ b/src/views/components/SmartTaskTitleInput.css @@ -93,11 +93,14 @@ border: none; background-color: var(--joy-palette-neutral-softBg, #f0f4f8); overflow: auto; - transition: box-shadow 0.15s ease, background-color 0.15s ease; + transition: + box-shadow 0.15s ease, + background-color 0.15s ease; } .task-input:focus-within { - box-shadow: 0 0 0 2px var(--joy-palette-primary-outlinedBorder, rgba(11, 107, 203, 0.15)); + box-shadow: 0 0 0 2px + var(--joy-palette-primary-outlinedBorder, rgba(11, 107, 203, 0.15)); } .task-input:hover:not(:focus-within) {