Compare commits

...

179 Commits

Author SHA1 Message Date
ricoberger
63f7ab7bf6 Prepare v1.4.1 Release 2024-08-07 17:38:04 +02:00
Rico Berger
676ff316d7 [core] Fix Warnings and Regenerate Splash Screens (#186)
This commit fixes the following warnings for the web build:

```
Warning: In index.html:38: Local variable for "serviceWorkerVersion" is deprecated. Use "{{flutter_service_worker_version}}" template token instead.
Warning: In index.html:60: "FlutterLoader.loadEntrypoint" is deprecated. Use "FlutterLoader.load" instead.
```

To re-add the slash screen we alsow run the
`flutter pub run flutter_native_splash:create` command again, which also
updated the splash screens for iOS and Android.

Last but not least this commit also fixes the following warnings for the
Windows build:

```
windows/runner/flutter_window.cpp does not ensure the show window callback is called, updating.
windows/flutter/CMakeLists.txt does not use FLUTTER_TARGET_PLATFORM, updating.
```
2024-08-07 17:34:19 +02:00
Rico Berger
3eccb0bd4a [core] Fix Web Build (#185)
Fix web build be initializing `JustAudioMediaKit` only on Linux and
Windows where it is really used. The corresponding issue for the broken
web build can be found here
https://github.com/Pato05/just_audio_media_kit/issues/15.

To test the web build on every PR to avoid such issues, the CI/CD
pipeline for the web build is now also run on every PR. On PRs we skip
the upload to Cloudflare for the web build.
2024-08-06 17:05:26 +02:00
Rico Berger
351c61f613 [core] Fix Metadata for Flatpak (#184)
The Linux version of the app is distributed via Flatpak, this commit
fixes some issues shown in the validation on Flathub. This includes the
summary and branding color and the app icon which should be square
instead of round.
2024-08-06 14:27:09 +02:00
Rico Berger
333e762539 [core] Upload Raw Build in Windows CI/CD Pipeline (#183)
Upload the raw build of the app in the Windows CI/CD pipeline, so that
we can test the production build during a new release.

We also had to adjust the Windows runner to `windows-2019`, because the
build on `windows-latest` and `windows-2022` can not be startet after
downloading it.
2024-08-06 09:40:13 +02:00
Rico Berger
280a222210 [podcast] Fix Audio Playback on Windows and Linux (#182)
Fix the audio playback on Windows and Linux for the podcast player by
adding the missing initialization for `JustAudioMediaKit`.
2024-08-06 07:45:15 +02:00
ricoberger
4853eeb0a8 Add Verification File for Flathub 2024-08-04 18:21:27 +02:00
ricoberger
9e9bf01b5b Fix Issues in app.feeddeck.feeddeck.metainfo.xml File 2024-08-04 18:09:59 +02:00
ricoberger
8989442fc1 Update Description in README 2024-08-04 15:12:13 +02:00
ricoberger
befe5b5977 Prepare v1.4.0 Release 2024-08-04 14:38:08 +02:00
dependabot[bot]
11585f284c Bump the pub group in /app with 12 updates (#181)
* Bump the pub group in /app with 12 updates

Bumps the pub group in /app with 12 updates:

| Package | From | To |
| --- | --- | --- |
| [app_links](https://github.com/llfbandit/app_links) | `6.1.3` | `6.1.4` |
| [flutter_cache_manager](https://github.com/Baseflow/flutter_cache_manager) | `3.3.2` | `3.4.0` |
| [flutter_native_splash](https://github.com/jonbhanson/flutter_native_splash) | `2.4.0` | `2.4.1` |
| [http](https://github.com/dart-lang/http/tree/master/pkgs) | `1.2.1` | `1.2.2` |
| [just_audio](https://github.com/ryanheise/just_audio) | `0.9.38` | `0.9.39` |
| [just_audio_background](https://github.com/ryanheise/just_audio) | `0.0.1-beta.12` | `0.0.1-beta.13` |
| [just_audio_media_kit](https://github.com/Pato05/just_audio_media_kit) | `2.0.4` | `2.0.5` |
| [package_info_plus](https://github.com/fluttercommunity/plus_plugins/tree/main/packages/package_info_plus) | `8.0.0` | `8.0.1` |
| [purchases_flutter](https://github.com/RevenueCat/purchases-flutter) | `6.29.4` | `6.30.2` |
| [shared_preferences](https://github.com/flutter/packages/tree/main/packages/shared_preferences) | `2.2.3` | `2.3.0` |
| [supabase_flutter](https://github.com/supabase/supabase-flutter/tree/main/packages) | `2.5.6` | `2.5.11` |
| [timeago](https://github.com/andresaraujo/timeago.dart) | `3.6.1` | `3.7.0` |


Updates `app_links` from 6.1.3 to 6.1.4
- [Release notes](https://github.com/llfbandit/app_links/releases)
- [Commits](https://github.com/llfbandit/app_links/compare/6.1.3...6.1.4)

Updates `flutter_cache_manager` from 3.3.2 to 3.4.0
- [Commits](https://github.com/Baseflow/flutter_cache_manager/compare/flutter_cache_manager_v3.3.2...v3.4.0)

Updates `flutter_native_splash` from 2.4.0 to 2.4.1
- [Release notes](https://github.com/jonbhanson/flutter_native_splash/releases)
- [Changelog](https://github.com/jonbhanson/flutter_native_splash/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jonbhanson/flutter_native_splash/commits)

Updates `http` from 1.2.1 to 1.2.2
- [Release notes](https://github.com/dart-lang/http/releases)
- [Commits](https://github.com/dart-lang/http/commits/http-v1.2.2/pkgs)

Updates `just_audio` from 0.9.38 to 0.9.39
- [Release notes](https://github.com/ryanheise/just_audio/releases)
- [Commits](https://github.com/ryanheise/just_audio/compare/just_audio-v0.9.38...just_audio-v0.9.39)

Updates `just_audio_background` from 0.0.1-beta.12 to 0.0.1-beta.13
- [Release notes](https://github.com/ryanheise/just_audio/releases)
- [Commits](https://github.com/ryanheise/just_audio/compare/just_audio_background-v0.0.1-beta.12...just_audio_background-v0.0.1-beta.13)

Updates `just_audio_media_kit` from 2.0.4 to 2.0.5
- [Changelog](https://github.com/Pato05/just_audio_media_kit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Pato05/just_audio_media_kit/compare/v2.0.4...v2.0.5)

Updates `package_info_plus` from 8.0.0 to 8.0.1
- [Release notes](https://github.com/fluttercommunity/plus_plugins/releases)
- [Commits](https://github.com/fluttercommunity/plus_plugins/commits/package_info_plus-v8.0.1/packages/package_info_plus)

Updates `purchases_flutter` from 6.29.4 to 6.30.2
- [Release notes](https://github.com/RevenueCat/purchases-flutter/releases)
- [Changelog](https://github.com/RevenueCat/purchases-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/RevenueCat/purchases-flutter/compare/6.29.4...6.30.2)

Updates `shared_preferences` from 2.2.3 to 2.3.0
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/shared_preferences-v2.3.0/packages/shared_preferences)

Updates `supabase_flutter` from 2.5.6 to 2.5.11
- [Changelog](https://github.com/supabase/supabase-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/supabase/supabase-flutter/commits/supabase_flutter-v2.5.11/packages)

Updates `timeago` from 3.6.1 to 3.7.0
- [Commits](https://github.com/andresaraujo/timeago.dart/commits)

---
updated-dependencies:
- dependency-name: app_links
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: flutter_cache_manager
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: flutter_native_splash
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: http
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: just_audio
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: just_audio_background
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: just_audio_media_kit
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: package_info_plus
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: purchases_flutter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: shared_preferences
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: supabase_flutter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: timeago
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update `Podfile.lock`

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-08-04 14:17:42 +02:00
dependabot[bot]
9503943b71 Bump the npm group in /landing with 8 updates (#180)
* Bump the npm group in /landing with 8 updates

Bumps the npm group in /landing with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [@headlessui/react](https://github.com/tailwindlabs/headlessui/tree/HEAD/packages/@headlessui-react) | `2.1.1` | `2.1.2` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.14.9` | `22.0.2` |
| [eslint](https://github.com/eslint/eslint) | `8.57.0` | `9.8.0` |
| [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `14.2.4` | `14.2.5` |
| [next](https://github.com/vercel/next.js) | `14.2.4` | `14.2.5` |
| [postcss](https://github.com/postcss/postcss) | `8.4.39` | `8.4.40` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss) | `3.4.4` | `3.4.7` |
| [typescript](https://github.com/Microsoft/TypeScript) | `5.5.2` | `5.5.4` |


Updates `@headlessui/react` from 2.1.1 to 2.1.2
- [Release notes](https://github.com/tailwindlabs/headlessui/releases)
- [Changelog](https://github.com/tailwindlabs/headlessui/blob/main/packages/@headlessui-react/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/headlessui/commits/@headlessui/react@v2.1.2/packages/@headlessui-react)

Updates `@types/node` from 20.14.9 to 22.0.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 8.57.0 to 9.8.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.57.0...v9.8.0)

Updates `eslint-config-next` from 14.2.4 to 14.2.5
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.2.5/packages/eslint-config-next)

Updates `next` from 14.2.4 to 14.2.5
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.2.4...v14.2.5)

Updates `postcss` from 8.4.39 to 8.4.40
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.39...8.4.40)

Updates `tailwindcss` from 3.4.4 to 3.4.7
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.7/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.4...v3.4.7)

Updates `typescript` from 5.5.2 to 5.5.4
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.5.2...v5.5.4)

---
updated-dependencies:
- dependency-name: "@headlessui/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: eslint
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: eslint-config-next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: postcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: typescript
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>

* Revert `eslint` Update

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-08-04 14:10:17 +02:00
ricoberger
d38cf80818 Merge branch 'main' of github.com:feeddeck/feeddeck 2024-07-27 10:15:32 +02:00
ricoberger
3e03f15825 Update Dependencies for Email Templates 2024-07-27 10:15:06 +02:00
dependabot[bot]
99e0538596 Bump braces from 3.0.2 to 3.0.3 in /landing (#178)
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-27 10:13:20 +02:00
dependabot[bot]
2a209519e1 Bump the npm group in /landing with 8 updates (#174)
* Bump the npm group in /landing with 8 updates

Bumps the npm group in /landing with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [@headlessui/react](https://github.com/tailwindlabs/headlessui/tree/HEAD/packages/@headlessui-react) | `2.0.4` | `2.1.1` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.13.0` | `20.14.9` |
| [eslint](https://github.com/eslint/eslint) | `8.57.0` | `9.6.0` |
| [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `14.2.3` | `14.2.4` |
| [next](https://github.com/vercel/next.js) | `14.2.3` | `14.2.4` |
| [postcss](https://github.com/postcss/postcss) | `8.4.38` | `8.4.39` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss) | `3.4.3` | `3.4.4` |
| [typescript](https://github.com/Microsoft/TypeScript) | `5.4.5` | `5.5.2` |


Updates `@headlessui/react` from 2.0.4 to 2.1.1
- [Release notes](https://github.com/tailwindlabs/headlessui/releases)
- [Changelog](https://github.com/tailwindlabs/headlessui/blob/main/packages/@headlessui-react/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/headlessui/commits/@headlessui/react@v2.1.1/packages/@headlessui-react)

Updates `@types/node` from 20.13.0 to 20.14.9
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 8.57.0 to 9.6.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.57.0...v9.6.0)

Updates `eslint-config-next` from 14.2.3 to 14.2.4
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.2.4/packages/eslint-config-next)

Updates `next` from 14.2.3 to 14.2.4
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.2.3...v14.2.4)

Updates `postcss` from 8.4.38 to 8.4.39
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.38...8.4.39)

Updates `tailwindcss` from 3.4.3 to 3.4.4
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.4/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.3...v3.4.4)

Updates `typescript` from 5.4.5 to 5.5.2
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.5...v5.5.2)

---
updated-dependencies:
- dependency-name: "@headlessui/react"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: eslint
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: eslint-config-next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: postcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: typescript
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>

* Revert `eslint` Update

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-07-27 10:09:22 +02:00
dependabot[bot]
461dc6f384 Bump the pub group in /app with 6 updates (#176)
* Bump the pub group in /app with 6 updates

Bumps the pub group in /app with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [app_links](https://github.com/llfbandit/app_links) | `6.1.1` | `6.1.3` |
| [flutter_markdown](https://github.com/flutter/packages/tree/main/packages) | `0.7.1` | `0.7.3` |
| [purchases_flutter](https://github.com/RevenueCat/purchases-flutter) | `6.29.2` | `6.29.4` |
| [sign_in_with_apple](https://github.com/aboutyou/dart_packages) | `6.1.0` | `6.1.1` |
| [supabase_flutter](https://github.com/supabase/supabase-flutter/tree/main/packages) | `2.5.4` | `2.5.6` |
| [url_launcher](https://github.com/flutter/packages/tree/main/packages/url_launcher) | `6.2.6` | `6.3.0` |


Updates `app_links` from 6.1.1 to 6.1.3
- [Release notes](https://github.com/llfbandit/app_links/releases)
- [Commits](https://github.com/llfbandit/app_links/compare/6.1.1...6.1.3)

Updates `flutter_markdown` from 0.7.1 to 0.7.3
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/flutter_markdown-v0.7.3/packages)

Updates `purchases_flutter` from 6.29.2 to 6.29.4
- [Release notes](https://github.com/RevenueCat/purchases-flutter/releases)
- [Changelog](https://github.com/RevenueCat/purchases-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/RevenueCat/purchases-flutter/compare/6.29.2...6.29.4)

Updates `sign_in_with_apple` from 6.1.0 to 6.1.1
- [Release notes](https://github.com/aboutyou/dart_packages/releases)
- [Commits](https://github.com/aboutyou/dart_packages/commits)

Updates `supabase_flutter` from 2.5.4 to 2.5.6
- [Changelog](https://github.com/supabase/supabase-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/supabase/supabase-flutter/commits/supabase_flutter-v2.5.6/packages)

Updates `url_launcher` from 6.2.6 to 6.3.0
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/url_launcher-v6.3.0/packages/url_launcher)

---
updated-dependencies:
- dependency-name: app_links
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: flutter_markdown
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: purchases_flutter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: sign_in_with_apple
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: supabase_flutter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: url_launcher
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Podfile.lock

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-07-27 10:07:31 +02:00
dependabot[bot]
409aa51f1c Bump docker/build-push-action from 5 to 6 in the github-actions group (#175)
Bumps the github-actions group with 1 update: [docker/build-push-action](https://github.com/docker/build-push-action).


Updates `docker/build-push-action` from 5 to 6
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-27 10:02:17 +02:00
Rico Berger
3620fcb5b0 [core] Wrap Actions in SafeArea Widget (#172)
With this commit we are wrapping all action widgets in a `SafeArea`
widget, to improve the alignment of the actions.
2024-06-08 18:30:04 +02:00
Rico Berger
ca7c22b0d7 Fix ESLint Dependency Mismatch (#171) 2024-06-08 18:20:26 +02:00
dependabot[bot]
318aeb4187 Bump the pub group across 1 directory with 17 updates (#167)
* Bump the pub group across 1 directory with 17 updates

Bumps the pub group with 16 updates in the /app directory:

| Package | From | To |
| --- | --- | --- |
| [app_links](https://github.com/llfbandit/app_links) | `3.5.1` | `6.1.1` |
| [cupertino_icons](https://github.com/flutter/packages/tree/main/third_party/packages) | `1.0.6` | `1.0.8` |
| [flutter_cache_manager](https://github.com/Baseflow/flutter_cache_manager) | `3.3.1` | `3.3.2` |
| [flutter_lints](https://github.com/flutter/packages/tree/main/packages) | `3.0.2` | `4.0.0` |
| [flutter_markdown](https://github.com/flutter/packages/tree/main/packages) | `0.6.22` | `0.7.1` |
| [html2md](https://github.com/jarontai/html2md) | `1.3.1` | `1.3.2` |
| [just_audio](https://github.com/ryanheise/just_audio) | `0.9.37` | `0.9.38` |
| [just_audio_background](https://github.com/ryanheise/just_audio) | `0.0.1-beta.11` | `0.0.1-beta.12` |
| [just_audio_media_kit](https://github.com/Pato05/just_audio_media_kit) | `2.0.2` | `2.0.4` |
| [package_info_plus](https://github.com/fluttercommunity/plus_plugins/tree/main/packages/package_info_plus) | `6.0.0` | `8.0.0` |
| [purchases_flutter](https://github.com/RevenueCat/purchases-flutter) | `6.24.0` | `6.29.2` |
| [shared_preferences](https://github.com/flutter/packages/tree/main/packages/shared_preferences) | `2.2.2` | `2.2.3` |
| [sign_in_with_apple](https://github.com/aboutyou/dart_packages) | `6.0.0` | `6.1.0` |
| [url_launcher](https://github.com/flutter/packages/tree/main/packages/url_launcher) | `6.2.5` | `6.2.6` |
| [window_manager](https://github.com/leanflutter/window_manager) | `0.3.8` | `0.3.9` |
| [youtube_explode_dart](https://github.com/Hexer10/youtube_explode_dart) | `2.1.0` | `2.2.1` |



Updates `app_links` from 3.5.1 to 6.1.1
- [Release notes](https://github.com/llfbandit/app_links/releases)
- [Changelog](https://github.com/llfbandit/app_links/blob/master/CHANGELOG.md)
- [Commits](https://github.com/llfbandit/app_links/compare/3.5.1...6.1.1)

Updates `cupertino_icons` from 1.0.6 to 1.0.8
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/cupertino_icons-v1.0.8/third_party/packages)

Updates `flutter_cache_manager` from 3.3.1 to 3.3.2
- [Commits](https://github.com/Baseflow/flutter_cache_manager/commits/flutter_cache_manager_v3.3.2)

Updates `flutter_lints` from 3.0.2 to 4.0.0
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/flutter_lints-v4.0.0/packages)

Updates `flutter_markdown` from 0.6.22 to 0.7.1
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/flutter_markdown-v0.7.1/packages)

Updates `html2md` from 1.3.1 to 1.3.2
- [Changelog](https://github.com/jarontai/html2md/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jarontai/html2md/commits)

Updates `just_audio` from 0.9.37 to 0.9.38
- [Release notes](https://github.com/ryanheise/just_audio/releases)
- [Commits](https://github.com/ryanheise/just_audio/compare/just_audio-v0.9.37...just_audio-v0.9.38)

Updates `just_audio_background` from 0.0.1-beta.11 to 0.0.1-beta.12
- [Release notes](https://github.com/ryanheise/just_audio/releases)
- [Commits](https://github.com/ryanheise/just_audio/compare/just_audio_background-v0.0.1-beta.11...just_audio_background-v0.0.1-beta.12)

Updates `just_audio_media_kit` from 2.0.2 to 2.0.4
- [Changelog](https://github.com/Pato05/just_audio_media_kit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Pato05/just_audio_media_kit/compare/v2.0.2...v2.0.4)

Updates `package_info_plus` from 6.0.0 to 8.0.0
- [Release notes](https://github.com/fluttercommunity/plus_plugins/releases)
- [Commits](https://github.com/fluttercommunity/plus_plugins/commits/package_info_plus-v8.0.0/packages/package_info_plus)

Updates `purchases_flutter` from 6.24.0 to 6.29.2
- [Release notes](https://github.com/RevenueCat/purchases-flutter/releases)
- [Changelog](https://github.com/RevenueCat/purchases-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/RevenueCat/purchases-flutter/compare/6.24.0...6.29.2)

Updates `shared_preferences` from 2.2.2 to 2.2.3
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/shared_preferences-v2.2.3/packages/shared_preferences)

Updates `sign_in_with_apple` from 6.0.0 to 6.1.0
- [Release notes](https://github.com/aboutyou/dart_packages/releases)
- [Commits](https://github.com/aboutyou/dart_packages/commits)

Updates `supabase_flutter` from 2.3.4 to 2.5.4
- [Changelog](https://github.com/supabase/supabase-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/supabase/supabase-flutter/commits/supabase_flutter-v2.5.4/packages)

Updates `url_launcher` from 6.2.5 to 6.2.6
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/url_launcher-v6.2.6/packages/url_launcher)

Updates `window_manager` from 0.3.8 to 0.3.9
- [Release notes](https://github.com/leanflutter/window_manager/releases)
- [Changelog](https://github.com/leanflutter/window_manager/blob/main/CHANGELOG.md)
- [Commits](https://github.com/leanflutter/window_manager/commits/v0.3.9)

Updates `youtube_explode_dart` from 2.1.0 to 2.2.1
- [Release notes](https://github.com/Hexer10/youtube_explode_dart/releases)
- [Changelog](https://github.com/Hexer10/youtube_explode_dart/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Hexer10/youtube_explode_dart/compare/v2.1.0...v2.2.1)

---
updated-dependencies:
- dependency-name: app_links
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: pub
- dependency-name: cupertino_icons
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: flutter_cache_manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: flutter_lints
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: pub
- dependency-name: flutter_markdown
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: html2md
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: just_audio
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: just_audio_background
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: just_audio_media_kit
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: package_info_plus
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: pub
- dependency-name: purchases_flutter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: shared_preferences
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: sign_in_with_apple
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: supabase_flutter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: url_launcher
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: window_manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: youtube_explode_dart
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Flutter Version and Podfile

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-06-08 17:59:59 +02:00
dependabot[bot]
1fb3bf63da Bump the npm group in /landing with 10 updates (#168)
Bumps the npm group in /landing with 10 updates:

| Package | From | To |
| --- | --- | --- |
| [@headlessui/react](https://github.com/tailwindlabs/headlessui/tree/HEAD/packages/@headlessui-react) | `1.7.18` | `2.0.4` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.12.2` | `20.13.0` |
| [eslint](https://github.com/eslint/eslint) | `8.57.0` | `9.4.0` |
| [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `14.1.4` | `14.2.3` |
| [next](https://github.com/vercel/next.js) | `14.1.4` | `14.2.3` |
| [react](https://github.com/facebook/react/tree/HEAD/packages/react) | `18.2.0` | `18.3.1` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `18.2.73` | `18.3.3` |
| [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) | `18.2.0` | `18.3.1` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `18.2.23` | `18.3.0` |
| [typescript](https://github.com/Microsoft/TypeScript) | `5.4.3` | `5.4.5` |


Updates `@headlessui/react` from 1.7.18 to 2.0.4
- [Release notes](https://github.com/tailwindlabs/headlessui/releases)
- [Changelog](https://github.com/tailwindlabs/headlessui/blob/main/packages/@headlessui-react/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/headlessui/commits/@headlessui/react@v2.0.4/packages/@headlessui-react)

Updates `@types/node` from 20.12.2 to 20.13.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 8.57.0 to 9.4.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.57.0...v9.4.0)

Updates `eslint-config-next` from 14.1.4 to 14.2.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.2.3/packages/eslint-config-next)

Updates `next` from 14.1.4 to 14.2.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.1.4...v14.2.3)

Updates `react` from 18.2.0 to 18.3.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v18.3.1/packages/react)

Updates `@types/react` from 18.2.73 to 18.3.3
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `react-dom` from 18.2.0 to 18.3.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v18.3.1/packages/react-dom)

Updates `@types/react-dom` from 18.2.23 to 18.3.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `typescript` from 5.4.3 to 5.4.5
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.3...v5.4.5)

---
updated-dependencies:
- dependency-name: "@headlessui/react"
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: eslint
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: eslint-config-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: react
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: react-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/react-dom"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-08 16:59:05 +02:00
Rico Berger
aa5c4861db Revert "Bump the npm group in /landing with 10 updates (#165)" (#166)
This reverts commit a7c5afdd83.
2024-05-01 21:08:28 +02:00
dependabot[bot]
a7c5afdd83 Bump the npm group in /landing with 10 updates (#165)
Bumps the npm group in /landing with 10 updates:

| Package | From | To |
| --- | --- | --- |
| [@headlessui/react](https://github.com/tailwindlabs/headlessui/tree/HEAD/packages/@headlessui-react) | `1.7.18` | `1.7.19` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.12.2` | `20.12.7` |
| [eslint](https://github.com/eslint/eslint) | `8.57.0` | `9.1.1` |
| [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `14.1.4` | `14.2.3` |
| [next](https://github.com/vercel/next.js) | `14.1.4` | `14.2.3` |
| [react](https://github.com/facebook/react/tree/HEAD/packages/react) | `18.2.0` | `18.3.1` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `18.2.73` | `18.3.1` |
| [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) | `18.2.0` | `18.3.1` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `18.2.23` | `18.3.0` |
| [typescript](https://github.com/Microsoft/TypeScript) | `5.4.3` | `5.4.5` |


Updates `@headlessui/react` from 1.7.18 to 1.7.19
- [Release notes](https://github.com/tailwindlabs/headlessui/releases)
- [Changelog](https://github.com/tailwindlabs/headlessui/blob/main/packages/@headlessui-react/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/headlessui/commits/@headlessui/react@v1.7.19/packages/@headlessui-react)

Updates `@types/node` from 20.12.2 to 20.12.7
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 8.57.0 to 9.1.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.57.0...v9.1.1)

Updates `eslint-config-next` from 14.1.4 to 14.2.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.2.3/packages/eslint-config-next)

Updates `next` from 14.1.4 to 14.2.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.1.4...v14.2.3)

Updates `react` from 18.2.0 to 18.3.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v18.3.1/packages/react)

Updates `@types/react` from 18.2.73 to 18.3.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `react-dom` from 18.2.0 to 18.3.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v18.3.1/packages/react-dom)

Updates `@types/react-dom` from 18.2.23 to 18.3.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `typescript` from 5.4.3 to 5.4.5
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.4.3...v5.4.5)

---
updated-dependencies:
- dependency-name: "@headlessui/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: eslint
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: eslint-config-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: react
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: react-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/react-dom"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-01 20:51:20 +02:00
Rico Berger
38fc655a53 [nitter] Disable Adding of new Sources (#163)
This commit disables the adding of new Nitter sources, because Nitter is
deprecated 😞 and adding new sources is not working anymore. Nitter
sources are also not updated anymore, because the update for Nitter
sources isn't working as well. To ensure that the Nitter sources are not
updated anymore the sources with type `nitter` are skipped in the
scheduler.

The Nitter source isn't removed completly, because we would also have to
cleanup the database and their might be items, which are bookmarked by
users.

See https://github.com/zedeus/nitter/issues/1155#issuecomment-1913361757
2024-04-06 17:22:27 +02:00
Rico Berger
4c34d33ac0 [x] Remove X Source (#162)
X (Twitter) was never supported and the code was never used to add a
source. We kept it in the hope that it will be possible again to use X
within the app. Since this isn't the case it is time to remove the code.
2024-04-06 13:00:12 +02:00
Rico Berger
eb9f84f650 [core] Update Flutter Version to 3.19.5 (#161) 2024-04-06 11:50:22 +02:00
dependabot[bot]
443e2db167 Bump the pub group in /app with 9 updates (#160)
* Bump the pub group in /app with 9 updates

Bumps the pub group in /app with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [app_links](https://github.com/llfbandit/app_links) | `3.5.0` | `3.5.1` |
| [flutter_lints](https://github.com/flutter/packages/tree/main/packages) | `3.0.1` | `3.0.2` |
| [flutter_markdown](https://github.com/flutter/packages/tree/main/packages) | `0.6.20+1` | `0.6.22` |
| [flutter_native_splash](https://github.com/jonbhanson/flutter_native_splash) | `2.3.10` | `2.4.0` |
| [http](https://github.com/dart-lang/http/tree/master/pkgs) | `1.2.0` | `1.2.1` |
| [package_info_plus](https://github.com/fluttercommunity/plus_plugins/tree/main/packages/package_info_plus) | `5.0.1` | `6.0.0` |
| [just_audio](https://github.com/ryanheise/just_audio) | `0.9.36` | `0.9.37` |
| [just_audio_media_kit](https://github.com/Pato05/just_audio_media_kit) | `2.0.1` | `2.0.2` |
| [package_info_plus](https://github.com/fluttercommunity/plus_plugins/tree/main/packages/package_info_plus) | `5.0.1` | `6.0.0` |
| [purchases_flutter](https://github.com/RevenueCat/purchases-flutter) | `6.22.0` | `6.24.0` |


Updates `app_links` from 3.5.0 to 3.5.1
- [Release notes](https://github.com/llfbandit/app_links/releases)
- [Changelog](https://github.com/llfbandit/app_links/blob/master/CHANGELOG.md)
- [Commits](https://github.com/llfbandit/app_links/commits/3.5.1)

Updates `flutter_lints` from 3.0.1 to 3.0.2
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/flutter_lints-v3.0.2/packages)

Updates `flutter_markdown` from 0.6.20+1 to 0.6.22
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/flutter_markdown-v0.6.22/packages)

Updates `flutter_native_splash` from 2.3.10 to 2.4.0
- [Release notes](https://github.com/jonbhanson/flutter_native_splash/releases)
- [Changelog](https://github.com/jonbhanson/flutter_native_splash/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jonbhanson/flutter_native_splash/compare/v2.3.10...v2.4.0)

Updates `http` from 1.2.0 to 1.2.1
- [Release notes](https://github.com/dart-lang/http/releases)
- [Commits](https://github.com/dart-lang/http/commits/http-v1.2.1/pkgs)

Updates `package_info_plus` from 5.0.1 to 6.0.0
- [Release notes](https://github.com/fluttercommunity/plus_plugins/releases)
- [Commits](https://github.com/fluttercommunity/plus_plugins/commits/package_info_plus-v6.0.0/packages/package_info_plus)

Updates `just_audio` from 0.9.36 to 0.9.37
- [Release notes](https://github.com/ryanheise/just_audio/releases)
- [Commits](https://github.com/ryanheise/just_audio/commits)

Updates `just_audio_media_kit` from 2.0.1 to 2.0.2
- [Changelog](https://github.com/Pato05/just_audio_media_kit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Pato05/just_audio_media_kit/compare/v2.0.1...v2.0.2)

Updates `package_info_plus` from 5.0.1 to 6.0.0
- [Release notes](https://github.com/fluttercommunity/plus_plugins/releases)
- [Commits](https://github.com/fluttercommunity/plus_plugins/commits/package_info_plus-v6.0.0/packages/package_info_plus)

Updates `purchases_flutter` from 6.22.0 to 6.24.0
- [Release notes](https://github.com/RevenueCat/purchases-flutter/releases)
- [Changelog](https://github.com/RevenueCat/purchases-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/RevenueCat/purchases-flutter/compare/6.22.0...6.24.0)

---
updated-dependencies:
- dependency-name: app_links
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: flutter_lints
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: flutter_markdown
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: flutter_native_splash
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: http
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: package_info_plus
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: pub
- dependency-name: just_audio
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: just_audio_media_kit
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: package_info_plus
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: pub
- dependency-name: purchases_flutter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix Podfile.lock

* Update Java and Gradle Version

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-04-01 18:33:26 +02:00
dependabot[bot]
347c570cde Bump the github-actions group with 1 update (#159)
Bumps the github-actions group with 1 update: [actions/configure-pages](https://github.com/actions/configure-pages).


Updates `actions/configure-pages` from 4 to 5
- [Release notes](https://github.com/actions/configure-pages/releases)
- [Commits](https://github.com/actions/configure-pages/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/configure-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 17:18:29 +02:00
dependabot[bot]
f8e2fa6128 Bump the npm group in /landing with 9 updates (#158)
Bumps the npm group in /landing with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.11.24` | `20.12.2` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `18.2.61` | `18.2.73` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `18.2.19` | `18.2.23` |
| [autoprefixer](https://github.com/postcss/autoprefixer) | `10.4.18` | `10.4.19` |
| [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `14.1.1` | `14.1.4` |
| [next](https://github.com/vercel/next.js) | `14.1.1` | `14.1.4` |
| [postcss](https://github.com/postcss/postcss) | `8.4.35` | `8.4.38` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss) | `3.4.1` | `3.4.3` |
| [typescript](https://github.com/Microsoft/TypeScript) | `5.3.3` | `5.4.3` |


Updates `@types/node` from 20.11.24 to 20.12.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/react` from 18.2.61 to 18.2.73
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `@types/react-dom` from 18.2.19 to 18.2.23
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `autoprefixer` from 10.4.18 to 10.4.19
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.18...10.4.19)

Updates `eslint-config-next` from 14.1.1 to 14.1.4
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.1.4/packages/eslint-config-next)

Updates `next` from 14.1.1 to 14.1.4
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.1.1...v14.1.4)

Updates `postcss` from 8.4.35 to 8.4.38
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.35...8.4.38)

Updates `tailwindcss` from 3.4.1 to 3.4.3
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/v3.4.3/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.4.1...v3.4.3)

Updates `typescript` from 5.3.3 to 5.4.3
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.3.3...v5.4.3)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@types/react-dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: autoprefixer
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: eslint-config-next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: postcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: typescript
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-01 17:18:06 +02:00
Rico Berger
9dbb979764 [core] Add Indexes to Improve Query Performance (#157)
Until now it could happen that the items for a column could not be
retrieved from the database, because of the set query timeout. In this
case we received the following error:

```
PostgrestException(message: canceling statement due to statement timeout, code: 57014, details: Internal Server Error, hint: null)
```

To fix this issue we added an `items_columnId_idx` index, so that the
items for a column are retrieved fast.

We also added some other useful indexes to improve the overall
performance of our queries.

Last but not least we also added an index to the `userId` columns as it
is recommended by Supabase to improve the performance of our RLS
policies.
2024-03-13 17:51:47 +01:00
dependabot[bot]
062db5d13a Bump the pub group in /app with 3 updates (#151)
* Bump the pub group in /app with 3 updates

Bumps the pub group in /app with 3 updates: [provider](https://github.com/rrousselGit/provider), [purchases_flutter](https://github.com/RevenueCat/purchases-flutter) and [sign_in_with_apple](https://github.com/aboutyou/dart_packages).


Updates `provider` from 6.1.1 to 6.1.2
- [Commits](https://github.com/rrousselGit/provider/compare/provider-v6.1.1...provider-v6.1.2)

Updates `purchases_flutter` from 6.21.1 to 6.22.0
- [Release notes](https://github.com/RevenueCat/purchases-flutter/releases)
- [Changelog](https://github.com/RevenueCat/purchases-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/RevenueCat/purchases-flutter/compare/6.21.1...6.22.0)

Updates `sign_in_with_apple` from 5.0.0 to 6.0.0
- [Release notes](https://github.com/aboutyou/dart_packages/releases)
- [Commits](https://github.com/aboutyou/dart_packages/commits)

---
updated-dependencies:
- dependency-name: provider
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: purchases_flutter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: sign_in_with_apple
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: pub
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Flutter Version and Podfile

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-03-02 11:08:50 +01:00
dependabot[bot]
788c7c9440 Bump the npm group in /landing with 2 updates (#156)
Bumps the npm group in /landing with 2 updates: [autoprefixer](https://github.com/postcss/autoprefixer) and [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next).


Updates `autoprefixer` from 10.4.17 to 10.4.18
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.17...10.4.18)

Updates `eslint-config-next` from 14.1.0 to 14.1.1
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.1.1/packages/eslint-config-next)

---
updated-dependencies:
- dependency-name: autoprefixer
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: eslint-config-next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-02 00:50:41 +01:00
ricoberger
aed602c55e [core] Adjust Dependabot Configuration
Adjust the Dependabot configuration to not update the
`/supabase/email-templates` folder anymore. This is done, because
Dependabot couldn't handle the `package.json` and `package-lock.json`
file very well and always wants to delete some required stuff.

Since the folder only contains our email templates it is also not
critical if the dependencies are not up to date.
2024-03-02 00:45:39 +01:00
dependabot[bot]
24f4648274 Bump the docker group in /supabase/functions/_cmd with 1 update (#153)
Bumps the docker group in /supabase/functions/_cmd with 1 update: lukechannings/deno.


Updates `lukechannings/deno` from v1.40.3 to v1.40.5

---
updated-dependencies:
- dependency-name: lukechannings/deno
  dependency-type: direct:production
  dependency-group: docker
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-02 00:22:45 +01:00
dependabot[bot]
d29d601513 Bump the github-actions group with 1 update (#152)
Bumps the github-actions group with 1 update: [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter).


Updates `release-drafter/release-drafter` from 5 to 6
- [Release notes](https://github.com/release-drafter/release-drafter/releases)
- [Commits](https://github.com/release-drafter/release-drafter/compare/v5...v6)

---
updated-dependencies:
- dependency-name: release-drafter/release-drafter
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-02 00:22:11 +01:00
dependabot[bot]
f21d38b080 Bump the npm-landing group in /landing with 6 updates (#150)
Bumps the npm-landing group in /landing with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.11.15` | `20.11.24` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `18.2.51` | `18.2.61` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `18.2.18` | `18.2.19` |
| [eslint](https://github.com/eslint/eslint) | `8.56.0` | `8.57.0` |
| [next](https://github.com/vercel/next.js) | `14.1.0` | `14.1.1` |
| [postcss](https://github.com/postcss/postcss) | `8.4.33` | `8.4.35` |


Updates `@types/node` from 20.11.15 to 20.11.24
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/react` from 18.2.51 to 18.2.61
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `@types/react-dom` from 18.2.18 to 18.2.19
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `eslint` from 8.56.0 to 8.57.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.56.0...v8.57.0)

Updates `next` from 14.1.0 to 14.1.1
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.1.0...v14.1.1)

Updates `postcss` from 8.4.33 to 8.4.35
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.33...8.4.35)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: "@types/react-dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: eslint
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: postcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-02 00:21:33 +01:00
ricoberger
a0c64508c9 Update License 2024-02-25 16:36:47 +01:00
Rico Berger
11084f04e9 [core] Upgrade Flutter Version (#149)
Upgrade the used version of Flutter to 3.19.1 and all used packages to
their latest version.

For the Android Version of the app, we also had to adjust some files,
because of the "Deprecated imperative apply of Flutter's Gradle
plugins". The steps we had to run for this can be found at
https://docs.flutter.dev/release/breaking-changes/flutter-gradle-plugin-apply
2024-02-25 16:23:33 +01:00
dependabot[bot]
2a8aa5f3c1 Bump the npm-email-templates group in /supabase/email-templates with 2 updates (#115)
* Bump the npm-email-templates group

Bumps the npm-email-templates group in /supabase/email-templates with 2 updates: [@react-email/components](https://github.com/resend/react-email/tree/HEAD/packages/components) and [react-email](https://github.com/resend/react-email/tree/HEAD/packages/react-email).


Updates `@react-email/components` from 0.0.11 to 0.0.14
- [Release notes](https://github.com/resend/react-email/releases)
- [Commits](https://github.com/resend/react-email/commits/v0.0.14/packages/components)

Updates `react-email` from 1.9.5 to 2.0.0
- [Release notes](https://github.com/resend/react-email/releases)
- [Commits](https://github.com/resend/react-email/commits/HEAD/packages/react-email)

---
updated-dependencies:
- dependency-name: "@react-email/components"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-email-templates
- dependency-name: react-email
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-email-templates
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump the npm-email-templates group

Bumps the npm-email-templates group in /supabase/email-templates with 2 updates: [@react-email/components](https://github.com/resend/react-email/tree/HEAD/packages/components) and [react-email](https://github.com/resend/react-email/tree/HEAD/packages/react-email).


Updates `@react-email/components` from 0.0.11 to 0.0.14
- [Release notes](https://github.com/resend/react-email/releases)
- [Commits](https://github.com/resend/react-email/commits/v0.0.14/packages/components)

Updates `react-email` from 1.9.5 to 2.0.0
- [Release notes](https://github.com/resend/react-email/releases)
- [Commits](https://github.com/resend/react-email/commits/HEAD/packages/react-email)

---
updated-dependencies:
- dependency-name: "@react-email/components"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-email-templates
- dependency-name: react-email
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-email-templates
...

Signed-off-by: dependabot[bot] <support@github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-02-24 09:09:40 +01:00
Rico Berger
c64b8026ae [core] Fix Blockquote Style (#148)
This commit fixes the style of blockquotes when we render the item
description as Markdown. Until now blockquotes had a weird blue
background, so that the text wasn't readable.

Now we are using the secondary color as background and we add a border on
the left site with the primary color.

We would also like to use italic as font family, but there is currently
a bug, so that the defined blockquote style is not applied. See
https://github.com/flutter/flutter/issues/81720
2024-02-23 18:39:10 +01:00
Rico Berger
ed76d85fd8 [core] Use Upstream just_audio_media_kit Version (#147)
Use the newest upstream version of the `just_audio_media_kit` package,
which removes the hard dependencies on the `media_kit_libs_linux` and
`media_kit_libs_windows_audio` packages, so that it shouldn't conflict
anymore with the usage of the `media_kit_libs_video` package.
2024-02-22 20:47:34 +01:00
Rico Berger
b2b3723ba8 [4chan] Improve Options Parsing (#146)
A 4chan source can now also be added via the RSS source type in the
Flutter app. If a user provides the RSS feed of an 4chan board, we check
if the url is related to 4chan and if this is the case, we use the 4chan
  instead of the RSS source type, similar to how it is handled for other
  sources like Medium, Reddit, etc.
2024-02-16 19:17:59 +01:00
Rico Berger
ca9ce54061 [mastodon] Add Support for Piped Videos (#145)
If a Mastodon post contains a Piped video it can now be played directly
within the app, similar to how it is handled for Nitter posts.
2024-02-14 19:01:56 +01:00
Rico Berger
8199c451b1 [reddit] Add Support for Piped Videos (#144)
If a Reddit post contains a Piped video it can now be played directly
within the app, similar to how it is handled in Nitter posts.
2024-02-14 19:00:51 +01:00
Rico Berger
66173d5a38 [lemmy] Add Support for Piped Videos (#143)
If a Lemmy post contains a Piped video it can now by played directly in
the app, similar to how it is handled for Nitter posts.
2024-02-14 18:59:14 +01:00
ricoberger
a5fba341d3 [core] Sort Imports 2024-02-14 18:36:54 +01:00
Rico Berger
689d3bd39b [4chan] Add Support for 4chan (#142)
This commit adds support for 4chan. This means that 4chan can be
selected as a new source type. When the 4chan source is selected a user
can select a board from which he wants to get the RSS feed.
2024-02-14 13:05:10 +01:00
Rico Berger
0b077ae973 [rss] Fix Image Parsing (#141)
The images of an RSS feed can now also start with `http://`, which is
necessary for some feeds.
2024-02-14 13:03:13 +01:00
Rico Berger
9a6bb033bf [core] Remove referer Check in image-proxy-v1 Function (#140) 2024-02-12 22:51:47 +01:00
ricoberger
7b84bab217 Prepare v1.3.0 Release 2024-02-12 19:51:12 +01:00
Rico Berger
1a56a8996e [core] Increase Update Interval for Reddit and Nitter (#138)
Reddit and Nitter are heavlily rate limited from time to time, to not
effect our premium users, by these limits, we decided to increase the
interval in which the Reddit and Nitter sources are updated for users
which are on the free tier.
2024-02-12 19:44:14 +01:00
Rico Berger
37bcc5e026 [nitter] Add Support for Piped Videos (#136)
The Nitter source now supports playing Piped Videos directly within the
app. For this we are checking if the Nitter post contains a piped.video
url and if this is the case we are using the newly added
`ItemPipedVideo` widget to render the video player, to allow users to
directly play the video within the app.

To support Piped videos we had to create a new `ItemPipedVideo` widget,
which is very similar to the `ItemYoutubeVideo` widget. This means on
the web version of FeedDeck we show the Video via an iframe and on the
other platforms via our `ItemVideoPlayer` widget. The main difference
between Piped and YouTube widget is the different client we use to fetch
the video urls. Besides the Piped API returns two different stream one
for the video and one for the audio, so that we had to add an additional
`audio` paramter to the `ItemVideoPlayer` widget, which allows us to
specify an additional audio source for a video.

NOTE: We had to add support for Piped, because Nitter automatically
converts the YouTube urls to the corresponding Piped urls.
2024-02-11 21:52:15 +01:00
Rico Berger
6a158f5176 [landing] Add Feature Images for Mobile Screens (#137)
Until now we always displayed the same feature images on the landing
page and it didn't matter if the user was on a desktop or mobile device.
This is now changed so that we display different images on mobile
devices (depending on the screen resolution).

Besides that we also moved the deprecated `themeColor` from the
`Metadata` to the `Viewport` and added it to all pages.

Last but not least we added some missing Android icons, which were
referenced in the `manifest.json` file, but where the icon didn't exist.
2024-02-11 21:26:47 +01:00
Rico Berger
0b7ca6cb14 [mastodon] Add Support for YouTube Videos (#135)
The Mastodon source supports YouTube Videos now. This means that if a
Mastodon post contains a link to a YouTube video as user can now
directly watch the video within the app.

If the post contains a video we render the YouTube video and the
description instead of the description, images and videos.
2024-02-10 21:25:16 +01:00
Rico Berger
303f78c3bc [reddit] Add Support for YouTube Videos (#134)
The Reddit source supports YouTube videos now. This means if a Reddit
post contains a link to a YouTube video, we render the video in the item
details, so that a user can directly watch the video.
2024-02-10 21:04:09 +01:00
ricoberger
c0c87e2c10 [core] Sort Imports 2024-02-10 20:43:18 +01:00
Rico Berger
babce57c80 [core] Fix Password Validations (#133)
This commit fixes the password validations. In #130 we introduced some
stronger password policies to forbid weak passwords, but forgot to
change it in all places. Now the same rules are also applying when a
user changes his password or resets his password.

During the sign in we do not use the same rules, to not block users
which have already signed up, with a password which doesn't match the
rules.
2024-02-10 15:31:56 +01:00
Rico Berger
ca5866ac13 [core] Add Continuous Delivery Workflow for Linux arm64 (#132)
Until now we had to manually build the app for Linux arm64 when we
created a new release. Now we are using ubicloud and the
`ubicloud-standard-2-arm` GitHub Action runner to build the app for
Linux arm64.
2024-02-10 14:58:27 +01:00
ricoberger
508e255c8b [core] Fix File 2024-02-06 21:05:40 +01:00
Rico Berger
aeeea4fd95 [core] Update macOS GitHub Action Runners (#131)
Update the used GitHub Action runners to `macos-14`, see
https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/
2024-02-02 17:36:46 +01:00
Rico Berger
6029ee539e [core] Forbid Weak Passwords (#130)
This commit improves our password policy, so that every user which signs
up must have a password with a minimum length of 8 characters, one upper
and lower case letter and one number.
2024-02-02 17:22:53 +01:00
Rico Berger
c9a596111c [rss] Do Not Remove HTML Tags (#129)
We do not remove HTML tags from the description of a RSS feed item
anymore, because:

- This didn't worked for all feeds, because we first removed the tags
  and then unescape the data, which didn't make sense
- We render the HTML to Makrdown in the frontend so that the description
  can contain HTML tags and is still properly rendered and in some case
  better rendered then before
2024-02-02 17:04:43 +01:00
Rico Berger
b8a73cc003 [core] Make Log Level Configurable (#128)
The log level is now configurable, via the `FEEDDECK_LOG_LEVEL`
environment variable. The environment variable can have the following
values: `debug`, `info`, `warning` or `error`.

With this change we also only log the response when getting and parsing
the feed fails when the log level is set to `debug`, also when the
actual message is still an error. This should reduce the noice in the
logs a lot and allows us to specially turn this on while debugging.
2024-02-02 16:52:14 +01:00
ricoberger
817eb4d9e8 [core] Update File 2024-02-02 16:06:44 +01:00
dependabot[bot]
20e3e736c2 Bump the docker group in /supabase/functions/_cmd with 1 update (#127)
Bumps the docker group in /supabase/functions/_cmd with 1 update: lukechannings/deno.


Updates `lukechannings/deno` from v1.40.2 to v1.40.3

---
updated-dependencies:
- dependency-name: lukechannings/deno
  dependency-type: direct:production
  dependency-group: docker
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-02 00:06:02 +01:00
dependabot[bot]
20352c0301 Bump the npm-landing group in /landing with 2 updates (#126)
Bumps the npm-landing group in /landing with 2 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react).


Updates `@types/node` from 20.11.13 to 20.11.15
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/react` from 18.2.48 to 18.2.51
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-02 00:05:29 +01:00
Rico Berger
e7b7000f46 [core] Add Open Link Action (#125)
This commit adds a new action to the menu shown when a user clicks
longer on the item in a column. The new "Open Link" action allows a user
to directly open the link of the item, so that the details modal must
not be opened anymore to open the link.
2024-01-31 21:09:34 +01:00
Rico Berger
fb3bec623a [core] Add Missing SafeArea Widget (#124)
Several widgets which where rendered within a modal bottom sheet didn't
used a `SafeArea` widget in the body of the `Scaffold` widget, so that
the action buttons on the bottom of the widget where not rendered in the
correct position.
2024-01-31 20:54:50 +01:00
dependabot[bot]
976c066004 Bump the pub group in /app with 2 updates (#121)
* Bump the pub group in /app with 2 updates

Bumps the pub group in /app with 2 updates: [purchases_flutter](https://github.com/RevenueCat/purchases-flutter) and [supabase_flutter](https://github.com/supabase/supabase-flutter/tree/main/packages).


Updates `purchases_flutter` from 6.18.0 to 6.19.0
- [Release notes](https://github.com/RevenueCat/purchases-flutter/releases)
- [Changelog](https://github.com/RevenueCat/purchases-flutter/blob/6.19.0/CHANGELOG.md)
- [Commits](https://github.com/RevenueCat/purchases-flutter/compare/6.18.0...6.19.0)

Updates `supabase_flutter` from 2.3.1 to 2.3.2
- [Changelog](https://github.com/supabase/supabase-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/supabase/supabase-flutter/commits/HEAD/packages)

---
updated-dependencies:
- dependency-name: purchases_flutter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: supabase_flutter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Flutter Version

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-01-31 20:28:49 +01:00
dependabot[bot]
304a9744a9 Bump the npm-landing group in /landing with 1 update (#120)
Bumps the npm-landing group in /landing with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).


Updates `@types/node` from 20.11.10 to 20.11.13
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-31 19:51:34 +01:00
Rico Berger
ee11cae8dc [landing] Add Lemmy Icon (#123)
Add an icon for Lemmy to the landing page. The new `lemmy` source type
was added in #94 and is now also added to the landing page for the next
release which should happen very soon.
2024-01-31 19:37:50 +01:00
Rico Berger
04314f116d [core] Fix Naming of Files (#122)
Fix the naming of some files: Instead of login we are always using the
term sign in and already renamed the `DesktopLoginManager` to
`DesktopSignInManager` in #106. During the renaming we forgot to rename
the file which is now done.

We also renamed the `sign_in_with_apple.dart` file to
`signin_with_apple.dart`, because the other files also do not contain an
underscore between sign and in.
2024-01-31 19:32:23 +01:00
ricoberger
b645244378 [core] Fix Assignees in Dependabot Configuration 2024-01-31 19:12:09 +01:00
dependabot[bot]
110ff56aa1 Bump the pub group in /app with 9 updates (#119)
* Bump the pub group in /app with 9 updates

Bumps the pub group in /app with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [cached_network_image](https://github.com/Baseflow/flutter_cached_network_image) | `3.3.0` | `3.3.1` |
| [flutter_native_splash](https://github.com/jonbhanson/flutter_native_splash) | `2.3.8` | `2.3.10` |
| [http](https://github.com/dart-lang/http/tree/master/pkgs) | `1.1.2` | `1.2.0` |
| [intl](https://github.com/dart-lang/i18n/tree/main/pkgs) | `0.18.1` | `0.19.0` |
| [purchases_flutter](https://github.com/RevenueCat/purchases-flutter) | `6.5.1` | `6.18.0` |
| [supabase_flutter](https://github.com/supabase/supabase-flutter/tree/main/packages) | `2.0.2` | `2.3.1` |
| [url_launcher](https://github.com/flutter/packages/tree/main/packages/url_launcher) | `6.2.2` | `6.2.4` |
| [window_manager](https://github.com/leanflutter/window_manager) | `0.3.7` | `0.3.8` |
| [youtube_explode_dart](https://github.com/Hexer10/youtube_explode_dart) | `2.0.4` | `2.1.0` |


Updates `cached_network_image` from 3.3.0 to 3.3.1
- [Commits](https://github.com/Baseflow/flutter_cached_network_image/compare/v3.3.0...v3.3.1)

Updates `flutter_native_splash` from 2.3.8 to 2.3.10
- [Release notes](https://github.com/jonbhanson/flutter_native_splash/releases)
- [Changelog](https://github.com/jonbhanson/flutter_native_splash/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jonbhanson/flutter_native_splash/commits)

Updates `http` from 1.1.2 to 1.2.0
- [Release notes](https://github.com/dart-lang/http/releases)
- [Commits](https://github.com/dart-lang/http/commits/HEAD/pkgs)

Updates `intl` from 0.18.1 to 0.19.0
- [Release notes](https://github.com/dart-lang/i18n/releases)
- [Commits](https://github.com/dart-lang/i18n/commits/intl-v0.19.0/pkgs)

Updates `purchases_flutter` from 6.5.1 to 6.18.0
- [Release notes](https://github.com/RevenueCat/purchases-flutter/releases)
- [Changelog](https://github.com/RevenueCat/purchases-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/RevenueCat/purchases-flutter/compare/6.5.1...6.18.0)

Updates `supabase_flutter` from 2.0.2 to 2.3.1
- [Changelog](https://github.com/supabase/supabase-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/supabase/supabase-flutter/commits/HEAD/packages)

Updates `url_launcher` from 6.2.2 to 6.2.4
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/url_launcher-v6.2.4/packages/url_launcher)

Updates `window_manager` from 0.3.7 to 0.3.8
- [Release notes](https://github.com/leanflutter/window_manager/releases)
- [Changelog](https://github.com/leanflutter/window_manager/blob/main/CHANGELOG.md)
- [Commits](https://github.com/leanflutter/window_manager/commits)

Updates `youtube_explode_dart` from 2.0.4 to 2.1.0
- [Release notes](https://github.com/Hexer10/youtube_explode_dart/releases)
- [Changelog](https://github.com/Hexer10/youtube_explode_dart/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Hexer10/youtube_explode_dart/compare/v2.0.4...v2.1.0)

---
updated-dependencies:
- dependency-name: cached_network_image
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: flutter_native_splash
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: http
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: intl
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: purchases_flutter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: supabase_flutter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: url_launcher
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: window_manager
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: youtube_explode_dart
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix Podfile.lock

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2024-01-31 19:10:56 +01:00
ricoberger
bbbeb9524f [core] Remove Deprecate Edge Functions
This commit removes the deprecated edge functions `add-source-v1` and
`profile-v1` from the stage deployment.
2024-01-31 19:07:01 +01:00
Rico Berger
90fc7532ba [core] Add Client Side Scraping of Sources (#118)
It is now possible to add and update sources via client side scraping.
For that a new edge function `add-or-update-source-v1` was added and the
old `add-source-v1` function was deprecated.

The new function accepts a new `feedData` field, which can contain the
feed for a source. If the field is provided we will not try to get the
feed for a source within our edge function and instead use the provided
data.

Currently this function is only used to add a Reddit source. Later we
plan to extend it for other sources and want to use it to update source
via the app, when the source provider makes heavy use of rate limiting.
2024-01-30 21:59:42 +01:00
dependabot[bot]
fac622ef97 Bump the docker group in /supabase/functions/_cmd with 1 update (#114)
Bumps the docker group in /supabase/functions/_cmd with 1 update: lukechannings/deno.


Updates `lukechannings/deno` from v1.38.4 to v1.40.2

---
updated-dependencies:
- dependency-name: lukechannings/deno
  dependency-type: direct:production
  dependency-group: docker
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-30 21:49:44 +01:00
dependabot[bot]
e29b94a576 Bump the github-actions group with 4 updates (#110)
Bumps the github-actions group with 4 updates: [actions/upload-artifact](https://github.com/actions/upload-artifact), [actions/configure-pages](https://github.com/actions/configure-pages), [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) and [actions/deploy-pages](https://github.com/actions/deploy-pages).


Updates `actions/upload-artifact` from 3 to 4
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

Updates `actions/configure-pages` from 3 to 4
- [Release notes](https://github.com/actions/configure-pages/releases)
- [Commits](https://github.com/actions/configure-pages/compare/v3...v4)

Updates `actions/upload-pages-artifact` from 2 to 3
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](https://github.com/actions/upload-pages-artifact/compare/v2...v3)

Updates `actions/deploy-pages` from 2 to 4
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](https://github.com/actions/deploy-pages/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/configure-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/upload-pages-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/deploy-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-30 21:49:03 +01:00
dependabot[bot]
911b3691b3 Bump the npm-landing group in /landing with 11 updates (#116)
Bumps the npm-landing group in /landing with 11 updates:

| Package | From | To |
| --- | --- | --- |
| [@headlessui/react](https://github.com/tailwindlabs/headlessui/tree/HEAD/packages/@headlessui-react) | `1.7.17` | `1.7.18` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.10.1` | `20.11.10` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `18.2.39` | `18.2.48` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `18.2.17` | `18.2.18` |
| [autoprefixer](https://github.com/postcss/autoprefixer) | `10.4.16` | `10.4.17` |
| [eslint](https://github.com/eslint/eslint) | `8.54.0` | `8.56.0` |
| [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `14.0.3` | `14.1.0` |
| [next](https://github.com/vercel/next.js) | `14.0.3` | `14.1.0` |
| [postcss](https://github.com/postcss/postcss) | `8.4.31` | `8.4.33` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss) | `3.3.5` | `3.4.1` |
| [typescript](https://github.com/Microsoft/TypeScript) | `5.3.2` | `5.3.3` |


Updates `@headlessui/react` from 1.7.17 to 1.7.18
- [Release notes](https://github.com/tailwindlabs/headlessui/releases)
- [Changelog](https://github.com/tailwindlabs/headlessui/blob/main/packages/@headlessui-react/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/headlessui/commits/@headlessui/react@v1.7.18/packages/@headlessui-react)

Updates `@types/node` from 20.10.1 to 20.11.10
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/react` from 18.2.39 to 18.2.48
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `@types/react-dom` from 18.2.17 to 18.2.18
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `autoprefixer` from 10.4.16 to 10.4.17
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.16...10.4.17)

Updates `eslint` from 8.54.0 to 8.56.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.54.0...v8.56.0)

Updates `eslint-config-next` from 14.0.3 to 14.1.0
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.1.0/packages/eslint-config-next)

Updates `next` from 14.0.3 to 14.1.0
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.0.3...v14.1.0)

Updates `postcss` from 8.4.31 to 8.4.33
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.31...8.4.33)

Updates `tailwindcss` from 3.3.5 to 3.4.1
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.3.5...v3.4.1)

Updates `typescript` from 5.3.2 to 5.3.3
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.3.2...v5.3.3)

---
updated-dependencies:
- dependency-name: "@headlessui/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: "@types/react-dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: autoprefixer
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: eslint
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
- dependency-name: eslint-config-next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
- dependency-name: postcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
- dependency-name: typescript
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-30 21:48:09 +01:00
Rico Berger
3a84376223 Add Assignees to Dependabot Configuration (#113) 2024-01-30 19:41:03 +01:00
Rico Berger
0f5a8e44f1 [core] Add Additional Header for Web Deployment (#112)
This commit adds the `X-Content-Type-Options`, `X-Frame-Options` and
`Referrer-Policy` headers to the web deployment of FeedDeck via the
`_headers` file.

See https://developers.cloudflare.com/pages/configuration/headers/
2024-01-30 19:27:47 +01:00
Rico Berger
5753fb2714 Update Flutter to Version 3.16.5 (#106)
Update the used Flutter version to 3.16.5 and the used packages to their
latest version.

The Supabase package contained some breaking changes:
- `functionUrl` is not exported anymore, so that it must be generated by
  ourselfs
- `Provider` was renamed to `OAuthProvider`
- The `signInWithApple` method was removed and is now implemented by us
  via the `sign_in_with_apple` package.

We also renamed the `DesktopLoginManager` to `DesktopSignInManager` to
use the same naming as in other places of the app, where we are always
using sign in and not login.
2023-12-21 17:24:07 +01:00
ricoberger
4008660a35 [core] Fix deno test Commands in Contributing Guidelines 2023-12-20 09:47:27 +01:00
Rico Berger
1cb58e1e0f [core] Refactor Tools and add get-feed Tool (#105)
This commit refactors the existing tools, by moving the tools logic to a
new `tools.ts` file, so that the main `cmd.ts` file remains clear.

Besides that we also add a new tool `get-feed` which can be used to run
the `getFeed` function from the command line. The function is called
with a source and returns the generated source and items, as they are
saved in the database by the `add-source-v1` Supabase edge function.
2023-12-17 18:04:53 +01:00
ricoberger
08e9170a80 [nitter] Adjust Header Handling 2023-12-17 13:51:03 +01:00
Rico Berger
4198a5bac6 [core] Replace Deprecated serve Function (#104)
The used `serve` function from the `std/server` module is deprecated and
must be replaced with `Deno.serve`. This was done within this commit.
2023-12-17 12:37:00 +01:00
ricoberger
295ae13705 [core] Remove deno.lock File 2023-12-17 12:11:31 +01:00
Rico Berger
0894f0e777 [core] Improve Error Handling for Feed Edge Functions (#103)
This commit improve the error handling for the edge function to add a
new source and the worker, so that we get more insights why a request
fails. A user will now also get a more detailed error why a source could
not be added.
2023-12-17 12:10:04 +01:00
ricoberger
2966ecc651 [rss] Fix Test Name 2023-12-12 22:13:47 +01:00
Rico Berger
49c168b5b2 [core] Disable Right Click for Item Actions on Web (#102)
On the web the right click on an item to show the actions, doesn't work
properly, because the browsers right click menu will be shown first. So
it doesn't make sense to show also our right click menu.
2023-12-12 22:03:32 +01:00
Rico Berger
8e0017e928 [rss] Show Videos from RSS Feeds (#101)
If an RSS feed contains a video within the `attachments` field, the video
will now be added to the `options` field of the item. In the Flutter
code we then check if the video field is present in the options and show
the video instead of an image in the details view of the item.
2023-12-12 21:49:45 +01:00
Rico Berger
982add8fbb [core] Update Deno Modules (#100)
This commit updates all used Deno modules to their latest version.

Since some of the used modules / functions were deprecated we had to
adjust our encrypt / descrypt functions and the generation of the source
and item ids, where we have to use a new md5 function.
2023-12-12 20:32:44 +01:00
Rico Berger
8065e19c85 [rss] Parse Atom and RDF Feeds from Websites (#99)
Until now we only checked if a website contained a RSS feed which can be
used for FeedDeck. Now we are also checking if the website contains a
Atom or RDF feed when no RSS feed was found.

For this we are checking `link` tag with the `type="application/atom+xml"`
attribute or a link tag with the `type="application/rdf+xml"` attribute.
2023-12-12 20:22:30 +01:00
Rico Berger
9e59439226 [core] Add Tests for Sources (#98)
This commit adds tests for all available sources.

This commit also fixes the parsing of Atom feeds for the RSS source,
where the `dc:date` field must be used for the `publishedAt` field.
2023-12-12 18:50:29 +01:00
Rico Berger
5087c299d3 [core] Add Test Setup for Deno (#97)
This commit uses the "Continuous Integration" GitHub Action, to run
tests for the Deno code, which is used by the Supabase functions and our
Docker containers.

This commit also adds a first test so that the `deno test` command does
not fail.
2023-12-03 15:55:04 +01:00
Rico Berger
bddf5874d4 [core] Fix Converting of HTML to Plain Text in Description (#96)
This commit fixes the conversion of HTML to plain text in the
description for an item. Until now it could happen, that the there was
no whitespace between some words after the conversion. This is now fixed
so that there is always a whitespace between words in the plain text.
2023-12-02 17:58:44 +01:00
Rico Berger
6c469e5d0d [core] Improve ItemVideoPlayer Widget (#95)
This commit adds two improvements to the `ItemVideoPlayer` widget. These
improvements are:
1. The padding for the widget is now defined within the widget, so that
   is must not be defined in the parent widget. With this change the
   widget follows the styling of our other widgets like `ItemMedia`.
2. On iOS the quality selection had a large bottom padding, this is now
   fixed, by using a `Wrap` widget instead of a `ListView` like we are
   using in the other modal bottom sheets which are showing some
   actions.
2023-12-02 16:51:56 +01:00
Rico Berger
8c88ece3dc [lemmy] Add Support for Lemmy (#94)
This commit adds support to add Lemmy RSS feeds to FeedDeck. A user can
provide the url of an Lemmy instance, the url of a community or of an
user.

The special thing of the Lemmy source in opposite to the normal RSS
source is, that we parse the provided link form a feed item, to check if
it contains a image, video or YouTube url, to apply some special
formatting.
2023-12-02 15:52:50 +01:00
Rico Berger
eb28a44cc8 [core] Fix Index Reset for Tabs in Small Deck Layout (#93)
The index was not reset in the `DeckLayoutSmall` widget, when the user
selected a new deck in the settings widget. This was caused because the
`DefaultTabController` was not rebuild after a new deck was selected, so
that the `initialIndex` value was not used.

This is now fixed by adding a `key` to the `DefaultTabController`, which
corresponds to the selected deck. This means if the user selects a new
deck in the settings the widget will be rebuild and the initial selected
tab will be the first one. If a user selects the same deck or switches
between the small and large layout the tab will be the formerly selected
one.
2023-12-01 18:09:54 +01:00
ricoberger
240e9e93d9 [podcast] Add Comment for the _player.pause() Hack 2023-12-01 18:03:28 +01:00
dependabot[bot]
eebec73fd2 Bump the npm-email-templates group in /supabase/email-templates with 1 update (#89)
* Bump the npm-email-templates group

Bumps the npm-email-templates group in /supabase/email-templates with 1 update: [@react-email/components](https://github.com/resendlabs/react-email/tree/HEAD/packages/components).

- [Release notes](https://github.com/resendlabs/react-email/releases)
- [Changelog](https://github.com/resendlabs/react-email/blob/canary/docs/changelog.mdx)
- [Commits](https://github.com/resendlabs/react-email/commits/v0.0.11/packages/components)

---
updated-dependencies:
- dependency-name: "@react-email/components"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-email-templates
...

Signed-off-by: dependabot[bot] <support@github.com>

* Run `npm install`

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2023-12-01 17:38:16 +01:00
dependabot[bot]
1b226791b4 Bump the pub group in /app with 1 update (#90)
Bumps the pub group in /app with 1 update: [msix](https://github.com/YehudaKremer/msix).

- [Release notes](https://github.com/YehudaKremer/msix/releases)
- [Changelog](https://github.com/YehudaKremer/msix/blob/main/CHANGELOG.md)
- [Commits](https://github.com/YehudaKremer/msix/compare/v3.16.6...v3.16.7)

---
updated-dependencies:
- dependency-name: msix
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-01 16:48:48 +01:00
dependabot[bot]
ad9885ce92 Bump the npm-landing group in /landing with 7 updates (#91)
Bumps the npm-landing group in /landing with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.8.10` | `20.10.1` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `18.2.33` | `18.2.39` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `18.2.14` | `18.2.17` |
| [eslint](https://github.com/eslint/eslint) | `8.52.0` | `8.54.0` |
| [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `14.0.1` | `14.0.3` |
| [next](https://github.com/vercel/next.js) | `14.0.1` | `14.0.3` |
| [typescript](https://github.com/Microsoft/TypeScript) | `5.2.2` | `5.3.2` |


Updates `@types/node` from 20.8.10 to 20.10.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/react` from 18.2.33 to 18.2.39
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `@types/react-dom` from 18.2.14 to 18.2.17
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `eslint` from 8.52.0 to 8.54.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.52.0...v8.54.0)

Updates `eslint-config-next` from 14.0.1 to 14.0.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.0.3/packages/eslint-config-next)

Updates `next` from 14.0.1 to 14.0.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v14.0.1...v14.0.3)

Updates `typescript` from 5.2.2 to 5.3.2
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.2.2...v5.3.2)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: "@types/react-dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: eslint
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
- dependency-name: eslint-config-next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: typescript
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-01 16:44:20 +01:00
dependabot[bot]
16418ab205 Bump the docker group in /supabase/functions/_cmd with 1 update (#92)
Bumps the docker group in /supabase/functions/_cmd with 1 update: lukechannings/deno.


---
updated-dependencies:
- dependency-name: lukechannings/deno
  dependency-type: direct:production
  dependency-group: docker
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-01 16:38:50 +01:00
Rico Berger
d9d82a1679 [core] Add Test Setup for Flutter (#87)
This commit adds a new "Continuous Integration" GitHub Action, which is
used to run the tests for the Flutter app (and later also for Deno).
This commit also adds a first test, so that the GitHub Action does not
fail.

This PR also removes the Visual Studio Code and Neovim configurations
from the contribution guide, since I'm not using it anymore and for that
I do not want to maintain it any longer.
2023-11-30 21:49:49 +01:00
ricoberger
ff52516324 Prepare v1.2.1 Release 2023-11-30 18:03:33 +01:00
Rico Berger
abd3c24f68 [core] Remove Blank in Item Preview Description (#86)
This commit removes all blank lines in the item preview description, so
that we do not render a blank line as the last line. This was done to
improve the style of the item previews, which looked ugly when the last
line was a blank line.
2023-11-29 21:47:53 +01:00
Rico Berger
04ef618295 [core] Add Right Click Support for Item Actions (#85)
Until now it was only possible to show the actions for an item by
pressing longer on the item. Now a user can also right click on the item
to display the actions which feels a bit more natural on desktop
devices.
2023-11-29 21:14:27 +01:00
Rico Berger
a58c93be8a [podcast] Stop Audio Playback on Windows and Linux (#84)
On Windows and Linux it could happen that the audio playback for a
podcast wasn't stopped when the item details view for a podcast item was
closed.

This commit "fixes" the problem, by pausing the audio player, before the
widget is disposed.

This commit also fixes the condition when the background audio services
should be initialized in the `main.dart` file. Instead of the macOS
check, we checked for iOS twice.
2023-11-29 21:06:06 +01:00
Rico Berger
5a8d6b34c1 [medium] Extend Filter Words List (#83) 2023-11-29 20:09:34 +01:00
ricoberger
9233e4d373 [core] Fix 2023-11-26 20:07:18 +01:00
Rico Berger
6e50af16a7 [core] Fix build.gradle File for Android Release (#82)
The change introduced in #71 so that we can run the Android build in a
GitHub action, broke the `flutter build appbundle` command to build the
Android version for the Google Play store. This commit should fix this,
so that we can build the Android version in a GitHub Action and for
Google Play.
2023-11-26 19:40:54 +01:00
ricoberger
046479071b Prepare v1.2.0 Release 2023-11-26 17:51:09 +01:00
Rico Berger
ffbed73669 [medium] Remove Spam (#79)
When using Medium as a source it is possible that the a lot of items
might be spam when following a tag. To reduce the spam, we filter these
items based on a word list and an calculated score. The score is
calculated by the number of words which are included in the title from
our word list.
2023-11-26 17:03:54 +01:00
Rico Berger
03371cf645 [reddit] Remove Tables from Description (#78)
When a Reddit post contained an image it was always rendered as table,
where the image was displayed in the left column and the author in the
right column. This looked very ugly in the app, so that we are now
removing all tables from the description of an Reddit post, so that the
image is rendered as large as possible and the author is displayed below
the image.
2023-11-26 16:55:17 +01:00
Rico Berger
eb606b5f6c [core] Improve Subtitle in Details View (#77)
This commit improves the displayed subtitle in the details view of an
item. For that we have adjusted the `ItemSubtitle` widget to diplay next
to the source title, author and publishing time an corresponding icon.
We also increased the space between the items and we are using a `|`
instead of a `/` as seperator.
2023-11-26 16:09:48 +01:00
Rico Berger
df927516b1 [core] Improve Icon Handling (#76)
Instead of defining the icons for a source only within the `SourceIcon`
widget, the icons are now defined as extension for the `FDSourceType`
enum. The background and foreground colors are also defined within the
enum now. This allows us to access the icon of a source outside of the
`SourceIcon` widget and we only have to touch the `source.dart` file
when adding a new source type.
2023-11-26 14:52:15 +01:00
Rico Berger
fa23e095e5 [core] Fix getMedia Function (#75)
In the `getMedia` function for Medium, Nitter, RSS and Tumblr we checked
the content and/or description of an RSS feed entry for a media file,
but we didn't pass the string to the `unescape` function first, so that
we might missed some media files, because our regular expression were
not able to find an image.

Now we are using the `unescape` function before using our regular
expression to find the image, similar to how we are also applying the
`unescape` function before we save the item description.
2023-11-25 18:24:22 +01:00
Rico Berger
2298176c3b [pinterest] Add Support for Pinterest (#74)
This commit adds a new source type "pinterest", which can be used to
follow the post of an user or a board on Pinterest. To use the new
source type a user can select the "Pinterest" item in the add source
modal. In the form a user can provide the username or board he wants to
follow via FeedDeck.

In the corresponding Supabase function we then convert the input
provided by the user to an valid RSS feed url for Pinterest. This means
that we have to add `/feed.rss` for users and `.rss` for boards to the
Pinterest url.

Then we generate the source and items as for the other sources and reuse
the existing components to render the preview and details item. We had
to adjust the rendering logic for these items, to ignore empty values,
from which also other sources will benefit.
2023-11-25 18:04:19 +01:00
Rico Berger
3f7caf4ad4 [core] Fix Decoding of Special Characters (#73)
We have to add the "charset" parameter to the "Content-Type" header when
we return json from one of the Supabase functions, so that special
characters are properly decoded in Flutter.
2023-11-25 00:00:22 +01:00
Rico Berger
db9363e7af [rss] Allow Users to Provide a Website URL (#72)
Users can now provide the URL of a website instead of the url of a RSS
feed via the input field for the RSS source.

This is possible because we are now trying to get and parse the RSS feed
for the provided url as usual, but if this operation fails, we try to
parse the text as html, so that we can check if it contains a
"<link type="application/rss+xml" href="RSS_FEED_URL">" tag. If this is
the case we are using this value to try to get and parse the RSS feed
again. If it fails again we are returning an error as before.
2023-11-24 23:11:50 +01:00
Rico Berger
ce36761c64 [core] Add GitHub Action for iOS and Android (#71)
This commit adds 2 new jobs to the existing "Continuous Delivery" GitHub
Action to test the build of the iOS and Android app.

For this we also had to adjust the "build.gradle" file for the Android
app, so that the test build in the GitHub Action is signed with dummy
credentials, since we do not provide the keystore properties.
2023-11-24 17:37:24 +01:00
Rico Berger
4e38cfdb5c [core] Update Flutter to Version 3.16.0 (#70)
Update the used Flutter version to 3.16.0 and all Flutter packages to
their latest version.

This commit also fixes all of the newly added analysis options and the
layout changes introduced with the new Flutter version (e.g. we have to
set the "tabAlignment" property in the "TabBar" widget).
2023-11-24 17:12:08 +01:00
Rico Berger
1c7c88a9ca [core] Submit "Add Source" Forms on Enter (#69)
All our forms were submitable via enter except the forms used to add a
new source to a column. This is now changed so that also these forms can
be submitted by pressing enter in a text field.
2023-11-07 23:12:46 +01:00
dependabot[bot]
c7d208de23 Bump the pub group in /app with 8 updates (#68)
* Bump the pub group in /app with 8 updates

Bumps the pub group in /app with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [flutter_lints](https://github.com/flutter/packages/tree/main/packages) | `2.0.3` | `3.0.1` |
| [flutter_native_splash](https://github.com/jonbhanson/flutter_native_splash) | `2.3.3` | `2.3.5` |
| [msix](https://github.com/YehudaKremer/msix) | `3.16.4` | `3.16.6` |
| [package_info_plus](https://github.com/fluttercommunity/plus_plugins/tree/main/packages/package_info_plus) | `4.1.0` | `4.2.0` |
| [purchases_flutter](https://github.com/RevenueCat/purchases-flutter) | `6.0.0` | `6.2.0` |
| [supabase_flutter](https://github.com/supabase/supabase-flutter/tree/main/packages) | `1.10.22` | `1.10.24` |
| [timeago](https://github.com/andresaraujo/timeago.dart) | `3.5.0` | `3.6.0` |
| [url_launcher](https://github.com/flutter/packages/tree/main/packages/url_launcher) | `6.1.14` | `6.2.1` |


Updates `flutter_lints` from 2.0.3 to 3.0.1
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/pigeon-v3.0.1/packages)

Updates `flutter_native_splash` from 2.3.3 to 2.3.5
- [Release notes](https://github.com/jonbhanson/flutter_native_splash/releases)
- [Changelog](https://github.com/jonbhanson/flutter_native_splash/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jonbhanson/flutter_native_splash/commits/v2.3.5)

Updates `msix` from 3.16.4 to 3.16.6
- [Release notes](https://github.com/YehudaKremer/msix/releases)
- [Changelog](https://github.com/YehudaKremer/msix/blob/main/CHANGELOG.md)
- [Commits](https://github.com/YehudaKremer/msix/compare/v3.16.4...v3.16.6)

Updates `package_info_plus` from 4.1.0 to 4.2.0
- [Release notes](https://github.com/fluttercommunity/plus_plugins/releases)
- [Commits](https://github.com/fluttercommunity/plus_plugins/commits/package_info_plus-v4.2.0/packages/package_info_plus)

Updates `purchases_flutter` from 6.0.0 to 6.2.0
- [Release notes](https://github.com/RevenueCat/purchases-flutter/releases)
- [Changelog](https://github.com/RevenueCat/purchases-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/RevenueCat/purchases-flutter/compare/6.0.0...6.2.0)

Updates `supabase_flutter` from 1.10.22 to 1.10.24
- [Changelog](https://github.com/supabase/supabase-flutter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/supabase/supabase-flutter/commits/supabase_flutter-v1.10.24/packages)

Updates `timeago` from 3.5.0 to 3.6.0
- [Commits](https://github.com/andresaraujo/timeago.dart/commits)

Updates `url_launcher` from 6.1.14 to 6.2.1
- [Release notes](https://github.com/flutter/packages/releases)
- [Commits](https://github.com/flutter/packages/commits/url_launcher-v6.2.1/packages/url_launcher)

---
updated-dependencies:
- dependency-name: flutter_lints
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: pub
- dependency-name: flutter_native_splash
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: msix
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: package_info_plus
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: purchases_flutter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: supabase_flutter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pub
- dependency-name: timeago
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
- dependency-name: url_launcher
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pub
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Flutter Packages

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2023-11-05 23:33:01 +01:00
dependabot[bot]
a7639344a1 Bump the npm-email-templates group in /supabase/email-templates with 1 update (#61)
* Bump the npm-email-templates group

Bumps the npm-email-templates group in /supabase/email-templates with 1 update: [@react-email/components](https://github.com/resendlabs/react-email/tree/HEAD/packages/components).

- [Release notes](https://github.com/resendlabs/react-email/releases)
- [Changelog](https://github.com/resendlabs/react-email/blob/main/docs/changelog.mdx)
- [Commits](https://github.com/resendlabs/react-email/commits/HEAD/packages/components)

---
updated-dependencies:
- dependency-name: "@react-email/components"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-email-templates
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Email Templates

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2023-11-05 23:07:07 +01:00
dependabot[bot]
ff76531962 Bump the npm-landing group in /landing with 7 updates (#60)
Bumps the npm-landing group in /landing with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.8.5` | `20.8.10` |
| [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `18.2.28` | `18.2.33` |
| [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `18.2.13` | `18.2.14` |
| [eslint](https://github.com/eslint/eslint) | `8.51.0` | `8.52.0` |
| [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `13.5.4` | `14.0.1` |
| [next](https://github.com/vercel/next.js) | `13.5.4` | `14.0.1` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss) | `3.3.3` | `3.3.5` |


Updates `@types/node` from 20.8.5 to 20.8.10
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@types/react` from 18.2.28 to 18.2.33
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

Updates `@types/react-dom` from 18.2.13 to 18.2.14
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

Updates `eslint` from 8.51.0 to 8.52.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.51.0...v8.52.0)

Updates `eslint-config-next` from 13.5.4 to 14.0.1
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/commits/v14.0.1/packages/eslint-config-next)

Updates `next` from 13.5.4 to 14.0.1
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v13.5.4...v14.0.1)

Updates `tailwindcss` from 3.3.3 to 3.3.5
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/compare/v3.3.3...v3.3.5)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: "@types/react"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: "@types/react-dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
- dependency-name: eslint
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm-landing
- dependency-name: eslint-config-next
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-landing
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-landing
- dependency-name: tailwindcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-landing
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-05 23:04:13 +01:00
dependabot[bot]
dc77f16a34 Bump the github-actions group with 1 update (#62)
* Bump the github-actions group with 1 update

Bumps the github-actions group with 1 update: [actions/setup-node](https://github.com/actions/setup-node).

- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Node Version

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: ricoberger <mail@ricoberger.de>
2023-11-05 22:59:13 +01:00
Rico Berger
bcd03e7e60 [core] Add Custom Cache Manager (#67)
This commit adds a custom cache manager "CustomCacheManager" which is
used in the "CachedNetworkImage" widget. The custom cache manager is
required, so that we can adjust the stale periode of cached images. By
default the package used 30 days as stale periode, but for our use case
7 days should be enough and we can reduce the storage used by the app.

Note: We also fixed the "run.sh" script to work with devices where the
name contains a space.
2023-11-05 17:35:37 +01:00
Rico Berger
92bea5d715 [core] Improve Media Handling (#66)
This commit improves / simplifies the media handling within the app.
Until now we always had to provide the type of the media file (item
media / source icon) when we wanted to display it. This is now not
necessary anymore. Instead we always display the image from it's
original path when the url starts with "http://" or "https://".
Additionally we also check the platform to proxy the image request on
the web. If the image doesn't start with "http://" or "https://" we
always try to display the image from the Supabase storage.

For this we also adjusted the corresponding Deno function, so that we
check if the image starts with "http://" or "https://" before we upload
it to the Supabase storage. If this is the case we upload the source
icon to the Supabase storage. If the upload fails, we will use the
original path of the icon.

Last but not least this commit also introduces our own
"CachedNetworkImage" widget, which wraps the original
"CachedNetworkImage" widget. Our own widget will ensure that we use the
correct url for the image request, so that we do not have to use this
function all over the app anymore. Later this widget can also be used to
introduce our own cache manager.
2023-11-04 18:27:17 +01:00
Rico Berger
37cd4dff6f [core] Run "deno fmt" (#65)
Format the Deno code via "deno fmt" to use the defined code style from
the "deno.json" file.
2023-11-04 15:45:42 +01:00
Rico Berger
d62bf10eaf [github] Fix Icons in Item Preview (#64)
The icons for GitHub items were not shown, because we did not set the
correct "sourceIconType", which was required for the "ItemSource"
widget.
2023-11-04 11:48:12 +01:00
Rico Berger
3afbe5674b [core] Add Development Setup for Neovim (#63)
Add some stuff to make the development with Neovim easier:

- Add a "deno.json" file, which is required by the Deno language server,
  when working in Neovim to detect the "import_map.json" file.
- Add a "run.sh" script to easily run the Flutter app from the command
  line.
- Add the "run.sh" script and an example for Neovim to the contributing
  guide.
2023-11-04 11:47:53 +01:00
Rico Berger
6d5a699db6 [core] Add Missing Divider to Video Quality Selection (#58)
In the modal bottom sheet where a user can select the video quality the
dividers between the different qualities were missing. This commit adds
the missing divider, so that the modal bottom sheet looks similar to the
other modal bottom sheets we are using (e.g. sign out, account
settings).
2023-10-30 19:49:21 +01:00
Rico Berger
e19885a594 [core] Fix Modal Bottom Sheet Size for Images (#57)
The size of the modal bottom sheet to display images had always a max
width of 640px on large screens. This wasn't intended an the modal
bottom sheet should fill the whole screen. This is now fixed, so that
when a user clicks on an image in the details view of an item, the whole
screen is used to display the image.
2023-10-30 12:08:57 +01:00
Rico Berger
6e27eb751c [youtube] Add Desktop Support (#56)
It is now pissible to play YouTube videos on the native desktop clients.
To achieve this we removed the "youtube_player_iframe" package which was
used before to play YouTube video, but which only supported web, iOS and
Android as target platforms.

On the web we are now using our own implementation to render an iframe
with for the YouTube video.

On all other platforms we are now using the "youtube_explode_dart"
package to fetch the video urls for a YouTube video and then we display
them within our own video player (the "ItemVideoPlayer" widget which was
added in #51). We also decided to switch the package for the iOS and
Android implementation which already worked before, because we are now
able to play YouTube videos in fullscreen and we only have to maintain
an exception for the web implementation.

The "ItemVideoPlayer" widget now also supports multiple qualities of an
video via the "qualities" paramter, which allows a user to switch
between the different video qualities which are available for a YouTube
video. Last but not least the widget now uses our primary color for the
seek bar.
2023-10-29 22:48:54 +01:00
Rico Berger
8e3586f315 [github] Fix Notification Links for PRs (#55)
If a notification was related to a pull request the link we added to the
item didn't work. This should now be fixed, so that when a user clicks
on the item he is redirected to the correct pull request which is
associated with the item.

This commit also removes an unnecessary "console.log" statement.
2023-10-29 13:49:06 +01:00
Rico Berger
e994ab6214 [core] Sign Out from Current Device (#54)
Until now a user was always signed out from all devices when he clicked
on the "Sign Out" button in the settings. Now we will display a actions
modal bottom sheet where a user can select if he wants to sign out from
the current device or from all devices.

For this we pass the [SignOutScope] to the "signOut" function of
Supabase. if the scope is "local" the user will be signed out from the
current device. If the scope is "global" the user will be signed out
from all devices.
2023-10-29 10:39:28 +01:00
Rico Berger
4906f9dc27 [core] Improve Tabs Handling in Small Deck Layout (#53)
This commit improves the handling of tabs in the samll deck layout. We
are now saving the selected tabs index in the newly added
"LayoutRepository" so that we can reuse the selected tab when a user
switches between the small and large layout. We can now also set the tab
which should be initially selected in the large layout when a user
selects a column in the navigation rail. Last but not least we can also
reset the initial tab index when a user selects a new deck in the
settings, so that we always display the first column instead of the
column with the same index as it was selected in the previous deck.
2023-10-28 17:36:01 +02:00
Rico Berger
55c6da07d9 [rss] Improve Rendering of Items (#52)
The items of an RSS feed are now rendered better, to achieve this we did
the following changes:

- Remove leading and trailing whitespaces from the item description
  which should be rendered.
- Check if the media file of an item is an SVG image. If this is the
  case we will not add it to the "media" field in the database, because
  currently the CachedNetworkImage widget can not render SVGs. If we
  want to render them, we run into serious performance issue so we skip
  them completly.
- Always assume that the content of an RSS feed contains HTML and render
  them as plain text in the preview and as markdown in the details.
  Since we also render images from the description now, we check if the
  "item.media" image should be rendered. If the description contains an
  image we do not render our own image. If the description doesn't
  contain a image we render it.
2023-10-28 11:37:00 +02:00
Rico Berger
8dc83a5d5a [mastodon] Add Support for Videos (#51)
It is now possible to play videos from toots within FeedDeck. For that
we are using the "madia_kit" package, which is already used for the
Podcast player on Windows and Linux.

The videos from a toot are saved within the "options.videos" field of an
item next to the "options.media" field. In the "ItemDetailsMastodon"
widget we are then checking if this field is present and contains a list
of video urls. These urls can then be played via the "ItemVideos"
widget.
2023-10-27 15:22:27 +02:00
ricoberger
94d5732f6a Fix App IDs used in Landing Page 2023-10-22 23:09:37 +02:00
ricoberger
f4a9f84061 Fix app.feeddeck.feeddeck.metainfo.xml 2023-10-22 20:28:10 +02:00
Rico Berger
f147481606 Prepare v1.1.1 Release (#40) 2023-10-22 18:06:51 +02:00
Rico Berger
ebb0b63411 [core] Improve Android App Icons (#48)
This commit improves the Android app icons, by adjusting the size of the
icons.
2023-10-22 17:56:04 +02:00
Rico Berger
8248816577 [core] Clear Cached Items (#47)
The cached items in the "ItemsRepositoryStore" are now cleared when a
user selects an active deck in the settings and when a user signes out
of the app.

This is done to force a reload of the items in a column, when a user
switches between decks. For me this works better because, when I switch
between decks I manually trigger a reload for all columns, which is now
not necessary anymore.
2023-10-22 13:29:58 +02:00
Rico Berger
db454b0ebc [core] Fix Number of Loaded Items per Fetch (#46)
We always loaded 51 items per fetch instead of 50 items, because we used
a range of 0 to 50 which includes the item at position 0 and at position
50. This is now fixed by adjusting the range to 0 to 49, so that exactly
50 items are loaded per fetch request.

This commit also improves the number of loaded items shown in the column
header. If the status of the ItemsRepository is "loaded" we add a small
"+" symbol behind the number to indicat that there are more items, which
could be loaded. If the last page was already fetched (status ==
"loadedLast") then the "+" symbol isn't shown.
2023-10-22 12:42:14 +02:00
Rico Berger
74664612fd [core] Fix ItemsRepository Status (#45)
This commit fixes the status of an ItemsRepository when the repository
is initalized from the ItemsRepositoryStore instead of the "_getItems"
function.

After the repository was initialized from the ItemsRepositoryStore we
always set the status of the repository to "loaded", also when we had
less then 50 items. Because of that we also always displayed the "Load
More" button. This is now fixed by adding the status of the repository
to the ItemsRepositoryStore, so that the "Load More" button is only
shown when there are more items to load.
2023-10-22 12:21:00 +02:00
Rico Berger
f60b8795dc [core] Fix Border Radius for Drawer (#44)
This commit fixes the border radius for the drawer used in the large
deck layout. Until now the drawer used the border radius on all edges.
This is now fixed to only use the border radius on the right side of the
drawer. This is more aligned how the border radius is used in the side
sheet for the item details, where we also only use it on the left side.
2023-10-22 11:50:00 +02:00
Rico Berger
a3ad273b5f [core] Fix Status Bar for iOS (#43)
The status bar wasn't visible on iOS when the application was launched.
This is now fixed so that a user can still see the current time, battery
life, etc. when the application is running.

This commit also updates the Podfile for iOS and macOS, which was not
done within #42, so that some dependencies were missing.
2023-10-22 11:34:24 +02:00
Rico Berger
50f1638805 [podcast] Fix Audio Player for Windows and Linux (#42)
Instead of using the "just_audio_windows" and "just_audio_mpv" packages
for Windows and Linux, we are now using "just_audio_media_kit", so that
the audio player is working reliable on these platforms.

Note: We have to adjust the Flatpak, to include the dependencies which
are required on Linux.
2023-10-20 20:09:15 +02:00
Rico Berger
cf8762560e [core] Add Privacy Policy and Terms & Conditions (#39)
This commit adds links to the privacy policy and terms & conditions to
the distributed apps as it is required for the in-app purchase
submission in the Apple App Store.

This commit also updates the terms & conditions to include a specify
section when FeedDeck is used via the Apple App Store, Google Play Store
or the Windows Store.
2023-10-18 21:19:40 +02:00
Rico Berger
f8262dbe7f [core] Enable In-App Purchases for Android (#38)
This commit enables in-app purchases for Android, so that a user can
also subscribe to FeedDeck Premium on Android.
2023-10-18 21:04:32 +02:00
Rico Berger
37b44da41f [podcast] Fix Duration and Play Button (#37)
This commit fixes two bugs within the Podcast player.

It could happen that the play time and remaining time was not shown
correctly in the player. This mainly occured in Safari and is now fixed
by not using a regular expression to show the time, but instead we have
added a new "_printDuration" function which handles the formatting of
the durations.

Not only, but mainly on Safari it could also happen, that once a Podcast
was started and then paused, the loading spinner was displayed and a
user could not continue with the Podcast. This is now fixed, by removing
the spinner and only show the play, pause or replay button. As loading
indication we are now only using the seek bar.

Last but not least this commit also improves the readability of the
code, for parsing the icon of a Podcast feed.
2023-10-18 19:06:49 +02:00
ricoberger
9693fefa81 Fix Linux Release 2023-10-16 22:14:25 +02:00
ricoberger
9ed9d732f6 Prepare v1.1.0 Release 2023-10-16 21:12:48 +02:00
Rico Berger
ef1b37995f [core] Fix Google Client ID (#35)
Fix the used Google Client ID required for the Android login. The Google
Client ID must also be changed in all the Supabase projects.
2023-10-16 20:37:37 +02:00
Rico Berger
8e1e1c0eca [core] Rework Profile Edge Function (#34)
This commit introduces a new "profile-v2" edge function and deprecates
the "profile-v1" edge function. We decided to provide a new edge
function for all profile related operation to improve the handling of
the different operation the edge function is responsible for.

The main differences to the "profile-v1" functions are:
- Pass the operation id within the request url instead of the body of
  the request.
- Move the operations for accounts (e.g. GitHub) to seperate files, to
  improve the readability of the function.
- Do not require the "sourceType" anymore, instead we are using the
  operation id and request method to determine the operation which
  should be executed
- The request body is now only used for the data of the corresponding
  account and not for any other information like the operation id and
  source information.
2023-10-14 21:20:08 +02:00
dependabot[bot]
4c0a1fd5ad Bump the github-actions group with 5 updates (#33)
Bumps the github-actions group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `3` | `4` |
| [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) | `2` | `3` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `2` | `3` |
| [docker/login-action](https://github.com/docker/login-action) | `2` | `3` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `4` | `5` |


Updates `actions/checkout` from 3 to 4
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

Updates `docker/setup-qemu-action` from 2 to 3
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3)

Updates `docker/setup-buildx-action` from 2 to 3
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

Updates `docker/login-action` from 2 to 3
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

Updates `docker/build-push-action` from 4 to 5
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-13 18:43:53 +02:00
dependabot[bot]
70c26e9fb1 Bump the docker group in /supabase/functions/_cmd with 1 update (#32)
Bumps the docker group in /supabase/functions/_cmd with 1 update: lukechannings/deno.


---
updated-dependencies:
- dependency-name: lukechannings/deno
  dependency-type: direct:production
  dependency-group: docker
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-13 18:43:16 +02:00
Rico Berger
40ed13cbba [core] Add Dependabot Configuration (#31)
Add a configuration for Dependabot to keep our dependencies up to date.
2023-10-13 18:07:24 +02:00
Rico Berger
2ee64724d0 [core] Update NPM Packages (#30)
Update the npm packages used by the email templates and the landing
page.
2023-10-13 17:46:44 +02:00
Rico Berger
88550940a3 [core] Update Flutter to v3.13.7 (#29)
Update the used Flutter version to 3.13.7 and update all Flutter
packages to their latest version.
2023-10-13 17:04:47 +02:00
Rico Berger
20aea17a55 [core] Fix Title Alignment (#28)
When we used the AppBar widget we did not specify the "centerTitle"
property, so that the title was aligned within the default of the
platform. This means on iOS and macOS the title was centered, but on
Android, Windows and Linux the title was aligned on the left side.

This wasn't intended and we want to have the same style on all
Platforms, so that the title is now centered on all Platforms like it
was already done on iOS and macOS.
2023-10-12 23:22:50 +02:00
Rico Berger
4393e3271e [core] Fix Vertical Scrolling (#27)
As reported in #25 the list of sources in a column can not be scrolled
vertically when there are a lot of sources which can not all be
displayed within the existing space.

This problem only occures when a user has no touch device or trackpad,
e.g. on Linux, Windows or the Web.

To fix this we changed the scroll behaviour in the app to allow
scrolling via drag gestures. For the reported case this means the list
of sources can be dragged to the right or left side to view all the
other sources which are hidden.
2023-10-12 21:31:29 +02:00
Rico Berger
0487dbdcde [core] Add In-App Purchases (#24)
We have to add in-app purchases for the iOS, macOS and Android store, so
that users can also get the premium features of the app without using
Stripe for payments.

The in-app purchases are only enabled when a user uses the app with the
default Supabase environment or with the Supabase environment provided
during build time. If a user uses his own Supabase instance, he will not
be able to upgrade to the premium tier via in-app purchases.

We are using RevenueCat for in-app purchases, which automatically sends
all the events for a user to the "revenuecat-webhooks-v1" edge function.
Depending on the received event we can then upgrade / downgrade the
users profile. To be able to use RevenueCat as an additional provider to
Stripe we also had to add a new "subscriptionProvider" provider column
to the "profiles" table, which stores the information via which provider
a user upgraded his account.
2023-10-12 19:53:11 +02:00
Rico Berger
58e38a0a10 [core] Add Flatpak Files to Build Archive (#23)
Instead of downloading the Flatpak files from GitHub in the
"app.feeddeck.feeddeck.yml" file, we are now adding the files to the
archive we create during the release process.
2023-10-11 18:31:29 +02:00
Rico Berger
e83b367e3f [core] Fix Update of Read State for Large List of Items (#22)
When a user scrolls through a list of items and loads more items via the
"Load More" button and then clicks on the mark all items as read button,
it could happen that the request fails, because Supabase can not handle
the update filter with a large list of item ids.

To avoid this error we are splitting the list of item ids provided in
the "updateReadStates" into chunks of 25 items for the in clause in the
update filter.
2023-10-08 20:24:39 +02:00
Rico Berger
b82b486314 [core] Use Published Date for Item Ingestion (#21)
For the item ingestion logic we are now also looking at the published
date for all entries in a RSS feed. If the published date is older then
the last update date of a source the item will be skipped. This way we
should reduce the number of duplicated items, where an entry was updated
in the RSS feed, so that it had a new id and was written again to the
database and not only updated.
2023-10-08 20:19:15 +02:00
Rico Berger
d292cd00b7 [youtube] Add Missing URL in isYoutubeUrl Function (#20)
In the "isYoutubeUrl" function we are checking if the provided url is
related to YouTube. For that we checked if the url starts with
"https://www.youtube.com/" or "https://m.youtube.com/", but we also have
to check if the url starts with "https://youtube.com/" which is used
when a users shares a link to a channel via the YouTube app.

In this commit we add the missing "https://youtube.com/" option to the
"isYoutubeUrl" function.
2023-10-07 19:19:39 +02:00
Rico Berger
86db47c291 [nitter] Allow Usage of Custom Nitter Instances (#19)
It is now possible to use a custom Nitter instances. This means a user
must not rely on our Nitter instance and can instead use his own
instance. To use a custom Nitter instance a user must provide the full
RSS feed url for the instance.
2023-10-03 21:51:09 +02:00
Rico Berger
181807e090 [rss] Allow RSS Feeds without "published" Field (#18)
If a RSS feed entry did not contain a "published" field, we skipped the
entry and didn't added it to the database. Now it is also possible to
use feeds without a "published" field. If a feed entry does not contain
the field it must contain a "updated" field, which we then use for the
"publishedAt" field in the database. If a feed entry doesn't contain one
of the two fields the entry is still skipped.
2023-10-03 21:38:30 +02:00
Rico Berger
fe24f1ea0d [podcast] Improve Parsing (#17)
This commit improves the parsing of the RSS feeds for a podcast, because
some podcasts were not working as expected:

- The "https://gotime.fm/rss" podcast uses the "itunes:image" field for
  the podcast icon instead of "image", so that we now looking at both
  fields to add the podcast icon.
- The "https://itsallwidgets.com/podcast/feed" podcast didn't contain a
  link in the entries, so that all entries were skipped. For that a
  podcast must not contain a link anymore to be parsed, but most contain
  a media file which can be played within the app.
2023-10-02 19:59:52 +02:00
Rico Berger
f4e96e32fd [core] Add "Get Started" Guide (#16)
This commit adds a "Get Started" guide for the mobile and desktop
version of FeedDeck. The guide describes the basic concepts and settings
of the app to make it easier to get started with the FeedDeck.

This is also used for the review process in the different app stores to
make it easier to get the app approved.
2023-10-02 18:03:05 +02:00
ricoberger
f1c4ce06fb [core] Fix app.feeddeck.feeddeck.yml 2023-10-01 10:16:08 +02:00
Rico Berger
af483e155b [core] Add Flatpak (#15)
Add all files to create a Flatpak which can be distributed via Flathub.

Signed-off-by: ricoberger <mail@ricoberger.de>
2023-09-30 12:02:13 +02:00
ricoberger
b4a2c261b5 [core] Add Issue and Pull Request Template
This commit adds two issue templates and a pull request template. A user
can now select between reporting a bug or requesting a new feature when
opening an issue. The pull request template provides some guidance on
naming the pull request and on the required description.
2023-09-22 20:26:58 +02:00
Rico Berger
4df54be0df [core] Fix Issues with App Submission (#14)
During the review of the submission of the iOS and macOS versions of
FeedDeck we encountered some problems, so that the app was rejected. For
that we had to make the following changes:

- Change the foreground and background color of the "Sign in with Apple"
  button. This means we are now using black as foreground and white as
  background color.
- Add the "Sign in with Apple" capability to the macOS version, to
  handle the sign in within the app as it is done for the iOS version.
- Add description in the "CreateDeck" widget, because it was confusing
  for the review and they were thinking that they had to provide their
  name.
2023-09-22 09:15:03 +02:00
347 changed files with 25292 additions and 7004 deletions

45
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,45 @@
---
name: Bug report
about: Create a report to help us improve
title: '[<SOURCE>]'
labels: bug
assignees: ''
---
<!--
Please add the source type for your bug to the title of the issue, e.g. "[rss] RSS Feed could not be parsed". When
your problem is not related to a source use "[core]", e.g. "[core] Feature xyz is not working"
-->
## Describe the Bug
A clear and concise description of what the bug is.
## Platform
- [ ] Android
- [ ] iOS
- [ ] Linux
- [ ] macOS
- [ ] Windows
- [ ] Web
## To Reproduce
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
## Expected behavior
A clear and concise description of what you expected to happen.
## Screenshots
If applicable, add screenshots to help explain your problem.
## Additional context
Add any other context about the problem here.

View File

@@ -0,0 +1,31 @@
---
name: Feature request
about: Suggest an idea for this project
title: '[<SOURCE>]'
labels: enhancement
assignees: ''
---
<!--
Please add the source type for your bug to the title of the issue, e.g. "[rss] RSS Feed could not be parsed". When
your problem is not related to a source use "core", e.g. "[core] Feature xyz is not working"
-->
## Is your feature request related to a problem? Please describe
A clear and concise description of what the problem is. Ex. I'm always
frustrated when [...]
## Describe the solution you'd like
A clear and concise description of what you want to happen.
## Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've
considered.
## Additional context
Add any other context or screenshots about the feature request here.

11
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,11 @@
<!--
Keep PR title verbose enough and add prefix telling about what source it touches e.g "[rss] Add feature xyz" or if the
the PR is not realated to a source use "[core]", e.g. "[core] Fix xyz".
If you add a breaking change within your PR you should add ":warning:" to the title,
e.g. ":warning: [core] My breaking change"
-->
<!--
Description of what have been changed. Please also reference an issue, when available.
-->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

47
.github/assets/badge-app-store.svg vendored Normal file
View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 120 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g>
<g>
<g>
<path d="M110.135,0L9.535,0C9.168,0 8.806,0 8.44,0.002C8.134,0.004 7.83,0.01 7.521,0.015C6.85,0.023 6.18,0.082 5.517,0.191C4.856,0.304 4.215,0.515 3.616,0.818C3.019,1.124 2.472,1.522 1.998,1.997C1.52,2.471 1.122,3.018 0.819,3.618C0.515,4.217 0.305,4.859 0.194,5.521C0.083,6.183 0.023,6.853 0.015,7.523C0.006,7.83 0.005,8.138 0,8.444L0,31.559C0.005,31.869 0.006,32.17 0.015,32.481C0.023,33.151 0.083,33.821 0.194,34.482C0.304,35.145 0.515,35.788 0.819,36.387C1.122,36.985 1.52,37.53 1.998,38.001C2.471,38.478 3.017,38.876 3.616,39.18C4.215,39.484 4.855,39.697 5.517,39.81C6.18,39.919 6.85,39.978 7.521,39.987C7.83,39.994 8.134,39.998 8.44,39.998C8.806,40 9.168,40 9.535,40L110.135,40C110.494,40 110.859,40 111.219,39.998C111.523,39.998 111.836,39.994 112.141,39.987C112.811,39.979 113.479,39.92 114.141,39.81C114.804,39.696 115.448,39.483 116.049,39.18C116.647,38.876 117.194,38.478 117.666,38.001C118.142,37.528 118.541,36.983 118.848,36.387C119.15,35.787 119.358,35.145 119.467,34.482C119.578,33.821 119.64,33.151 119.652,32.481C119.656,32.17 119.656,31.869 119.656,31.559C119.664,31.195 119.664,30.834 119.664,30.465L119.664,9.536C119.664,9.17 119.664,8.807 119.656,8.444C119.656,8.138 119.656,7.83 119.652,7.523C119.64,6.852 119.578,6.183 119.467,5.521C119.358,4.859 119.149,4.217 118.848,3.618C118.23,2.415 117.251,1.436 116.049,0.818C115.448,0.516 114.804,0.304 114.141,0.191C113.48,0.081 112.811,0.022 112.141,0.015C111.836,0.01 111.523,0.004 111.219,0.002C110.859,-0 110.494,-0 110.135,-0L110.135,0Z" style="fill:rgb(166,166,166);fill-rule:nonzero;"/>
<path d="M8.445,39.125C8.14,39.125 7.843,39.121 7.541,39.114C6.914,39.106 6.29,39.052 5.671,38.951C5.095,38.852 4.537,38.667 4.015,38.403C3.498,38.142 3.026,37.798 2.618,37.387C2.204,36.98 1.859,36.508 1.597,35.99C1.333,35.469 1.149,34.91 1.054,34.333C0.951,33.713 0.896,33.086 0.888,32.458C0.881,32.247 0.873,31.545 0.873,31.545L0.873,8.444C0.873,8.444 0.882,7.753 0.888,7.55C0.895,6.922 0.951,6.297 1.053,5.678C1.149,5.099 1.332,4.539 1.597,4.016C1.857,3.498 2.2,3.026 2.612,2.618C3.023,2.206 3.496,1.861 4.014,1.595C4.535,1.332 5.092,1.149 5.667,1.051C6.288,0.95 6.915,0.895 7.543,0.887L8.445,0.875L111.214,0.875L112.127,0.888C112.75,0.895 113.371,0.949 113.985,1.05C114.566,1.149 115.13,1.334 115.656,1.598C116.694,2.133 117.539,2.979 118.071,4.018C118.332,4.538 118.512,5.094 118.606,5.667C118.71,6.291 118.768,6.922 118.78,7.554C118.783,7.837 118.783,8.142 118.783,8.444C118.791,8.819 118.791,9.176 118.791,9.536L118.791,30.465C118.791,30.828 118.791,31.183 118.783,31.54C118.783,31.865 118.783,32.163 118.779,32.47C118.768,33.091 118.71,33.71 118.608,34.323C118.515,34.904 118.333,35.468 118.068,35.993C117.805,36.506 117.462,36.973 117.053,37.379C116.644,37.793 116.172,38.138 115.653,38.401C115.128,38.667 114.566,38.853 113.985,38.951C113.367,39.052 112.742,39.107 112.116,39.114C111.823,39.121 111.517,39.125 111.219,39.125L110.135,39.127L8.445,39.125Z" style="fill-rule:nonzero;"/>
</g>
<g id="_Group_">
<g id="_Group_2_" serif:id="_Group_2">
<g id="_Group_3_" serif:id="_Group_3">
<path id="_Path_" d="M24.769,20.301C24.791,18.606 25.682,17.036 27.125,16.149C26.21,14.842 24.729,14.041 23.134,13.991C21.455,13.815 19.827,14.996 18.971,14.996C18.099,14.996 16.782,14.008 15.363,14.038C13.498,14.098 11.797,15.135 10.89,16.766C8.956,20.114 10.399,25.035 12.251,27.742C13.178,29.067 14.261,30.547 15.679,30.495C17.066,30.437 17.584,29.61 19.258,29.61C20.917,29.61 21.403,30.495 22.849,30.462C24.338,30.437 25.275,29.13 26.17,27.792C26.836,26.848 27.348,25.804 27.688,24.7C25.924,23.954 24.771,22.216 24.769,20.301Z" style="fill:white;fill-rule:nonzero;"/>
<path id="_Path_2_" serif:id="_Path_2" d="M22.037,12.211C22.848,11.237 23.249,9.984 23.152,8.72C21.912,8.85 20.766,9.443 19.944,10.38C19.132,11.304 18.721,12.514 18.8,13.741C20.056,13.754 21.25,13.189 22.037,12.211Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</g>
<g>
<path d="M42.302,27.14L37.569,27.14L36.432,30.496L34.427,30.496L38.911,18.078L40.994,18.078L45.477,30.496L43.438,30.496L42.302,27.14ZM38.059,25.591L41.811,25.591L39.961,20.144L39.91,20.144L38.059,25.591Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M55.16,25.97C55.16,28.783 53.654,30.591 51.381,30.591C50.209,30.652 49.099,30.035 48.533,29.007L48.49,29.007L48.49,33.491L46.631,33.491L46.631,21.442L48.43,21.442L48.43,22.948L48.464,22.948C49.056,21.926 50.166,21.31 51.347,21.348C53.645,21.348 55.16,23.164 55.16,25.97ZM53.25,25.97C53.25,24.137 52.302,22.932 50.857,22.932C49.437,22.932 48.482,24.162 48.482,25.97C48.482,27.794 49.437,29.016 50.857,29.016C52.302,29.016 53.25,27.819 53.25,25.97Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M65.125,25.97C65.125,28.783 63.619,30.591 61.346,30.591C60.174,30.652 59.064,30.035 58.498,29.007L58.455,29.007L58.455,33.491L56.596,33.491L56.596,21.442L58.395,21.442L58.395,22.948L58.429,22.948C59.021,21.926 60.131,21.31 61.312,21.348C63.61,21.348 65.125,23.164 65.125,25.97ZM63.214,25.97C63.214,24.137 62.267,22.932 60.822,22.932C59.402,22.932 58.447,24.162 58.447,25.97C58.447,27.794 59.402,29.016 60.822,29.016C62.267,29.016 63.214,27.819 63.214,25.97L63.214,25.97Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M71.71,27.036C71.848,28.268 73.044,29.076 74.679,29.076C76.246,29.076 77.373,28.268 77.373,27.157C77.373,26.193 76.693,25.616 75.084,25.221L73.474,24.833C71.194,24.282 70.135,23.216 70.135,21.485C70.135,19.343 72.002,17.871 74.654,17.871C77.278,17.871 79.077,19.343 79.137,21.485L77.261,21.485C77.149,20.246 76.125,19.498 74.627,19.498C73.13,19.498 72.106,20.255 72.106,21.356C72.106,22.234 72.76,22.751 74.361,23.146L75.729,23.482C78.277,24.085 79.335,25.108 79.335,26.925C79.335,29.248 77.485,30.703 74.542,30.703C71.788,30.703 69.928,29.282 69.808,27.036L71.71,27.036Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M83.346,19.3L83.346,21.442L85.068,21.442L85.068,22.914L83.346,22.914L83.346,27.905C83.346,28.681 83.691,29.042 84.448,29.042C84.652,29.038 84.856,29.024 85.059,28.999L85.059,30.462C84.719,30.525 84.373,30.554 84.027,30.548C82.194,30.548 81.479,29.859 81.479,28.103L81.479,22.914L80.163,22.914L80.163,21.442L81.479,21.442L81.479,19.3L83.346,19.3Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M86.065,25.97C86.065,23.121 87.743,21.331 90.359,21.331C92.984,21.331 94.654,23.121 94.654,25.97C94.654,28.826 92.993,30.608 90.359,30.608C87.726,30.608 86.065,28.826 86.065,25.97ZM92.76,25.97C92.76,24.016 91.865,22.862 90.359,22.862C88.853,22.862 87.959,24.024 87.959,25.97C87.959,27.932 88.853,29.076 90.359,29.076C91.865,29.076 92.76,27.932 92.76,25.97L92.76,25.97Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M96.186,21.442L97.959,21.442L97.959,22.983L98.002,22.983C98.248,21.995 99.161,21.309 100.179,21.348C100.393,21.347 100.607,21.37 100.816,21.417L100.816,23.155C100.546,23.073 100.264,23.035 99.981,23.043C99.956,23.042 99.93,23.041 99.905,23.041C98.878,23.041 98.032,23.887 98.032,24.914C98.032,24.985 98.036,25.056 98.044,25.126L98.044,30.496L96.186,30.496L96.186,21.442Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M109.384,27.837C109.134,29.48 107.534,30.608 105.486,30.608C102.852,30.608 101.217,28.844 101.217,26.013C101.217,23.173 102.861,21.331 105.408,21.331C107.913,21.331 109.488,23.052 109.488,25.797L109.488,26.434L103.093,26.434L103.093,26.546C103.087,26.615 103.084,26.684 103.084,26.754C103.084,28.047 104.149,29.112 105.442,29.112C105.471,29.112 105.5,29.111 105.529,29.11C106.428,29.195 107.282,28.675 107.62,27.837L109.384,27.837ZM103.102,25.135L107.628,25.135C107.631,25.094 107.632,25.054 107.632,25.014C107.632,23.819 106.649,22.836 105.455,22.836C105.439,22.836 105.423,22.837 105.408,22.837C105.403,22.837 105.399,22.837 105.394,22.837C104.137,22.837 103.102,23.872 103.102,25.129C103.102,25.131 103.102,25.133 103.102,25.135L103.102,25.135Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</g>
</g>
<g id="_Group_4_" serif:id="_Group_4">
<g>
<path d="M37.826,8.731C37.889,8.726 37.952,8.724 38.015,8.724C39.463,8.724 40.655,9.916 40.655,11.364C40.655,11.475 40.648,11.586 40.634,11.696C40.634,13.602 39.604,14.698 37.826,14.698L35.671,14.698L35.671,8.731L37.826,8.731ZM36.598,13.854L37.723,13.854C37.76,13.856 37.797,13.857 37.835,13.857C38.864,13.857 39.71,13.011 39.71,11.981C39.71,11.89 39.704,11.799 39.69,11.708C39.702,11.623 39.708,11.538 39.708,11.452C39.708,10.42 38.859,9.571 37.827,9.571C37.792,9.571 37.757,9.572 37.723,9.574L36.598,9.574L36.598,13.854Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M41.681,12.444C41.674,12.377 41.671,12.309 41.671,12.241C41.671,11.071 42.634,10.108 43.804,10.108C44.974,10.108 45.937,11.071 45.937,12.241C45.937,12.309 45.934,12.377 45.928,12.444C45.934,12.513 45.938,12.582 45.938,12.651C45.938,13.822 44.975,14.785 43.804,14.785C42.634,14.785 41.671,13.822 41.671,12.651C41.671,12.582 41.674,12.513 41.681,12.444ZM45.014,12.444C45.014,11.468 44.575,10.897 43.806,10.897C43.033,10.897 42.599,11.468 42.599,12.444C42.599,13.428 43.033,13.995 43.806,13.995C44.575,13.995 45.014,13.424 45.014,12.444L45.014,12.444Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M51.573,14.698L50.651,14.698L49.721,11.381L49.65,11.381L48.724,14.698L47.811,14.698L46.569,10.195L47.471,10.195L48.277,13.631L48.344,13.631L49.27,10.195L50.122,10.195L51.048,13.631L51.118,13.631L51.921,10.195L52.81,10.195L51.573,14.698Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M53.854,10.195L54.709,10.195L54.709,10.91L54.775,10.91C55.006,10.385 55.547,10.061 56.119,10.108C56.156,10.105 56.192,10.104 56.229,10.104C57.032,10.104 57.694,10.765 57.694,11.568C57.694,11.64 57.688,11.712 57.678,11.783L57.678,14.698L56.789,14.698L56.789,12.006C56.789,11.282 56.475,10.922 55.817,10.922C55.801,10.922 55.785,10.921 55.769,10.921C55.203,10.921 54.736,11.388 54.736,11.954C54.736,11.991 54.738,12.027 54.742,12.063L54.742,14.698L53.854,14.698L53.854,10.195Z" style="fill:white;fill-rule:nonzero;"/>
<rect x="59.094" y="8.437" width="0.889" height="6.261" style="fill:white;fill-rule:nonzero;"/>
<path d="M61.218,12.444C61.211,12.377 61.208,12.309 61.208,12.241C61.208,11.071 62.171,10.108 63.342,10.108C64.512,10.108 65.475,11.071 65.475,12.241C65.475,12.309 65.472,12.377 65.465,12.444C65.472,12.513 65.475,12.582 65.475,12.651C65.475,13.821 64.512,14.785 63.342,14.785C62.171,14.785 61.208,13.821 61.208,12.651C61.208,12.582 61.211,12.513 61.218,12.444ZM64.551,12.444C64.551,11.468 64.112,10.897 63.343,10.897C62.57,10.897 62.136,11.468 62.136,12.444C62.136,13.428 62.57,13.995 63.343,13.995C64.112,13.995 64.551,13.424 64.551,12.444L64.551,12.444Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M66.401,13.424C66.401,12.614 67.004,12.146 68.076,12.08L69.295,12.01L69.295,11.621C69.295,11.146 68.981,10.877 68.374,10.877C67.877,10.877 67.534,11.059 67.435,11.377L66.575,11.377C66.666,10.604 67.393,10.108 68.415,10.108C69.543,10.108 70.18,10.67 70.18,11.621L70.18,14.698L69.325,14.698L69.325,14.065L69.254,14.065C68.964,14.526 68.446,14.797 67.902,14.772C67.855,14.777 67.808,14.779 67.761,14.779C67.017,14.779 66.404,14.169 66.401,13.424ZM69.295,13.04L69.295,12.663L68.196,12.733C67.576,12.775 67.294,12.986 67.294,13.383C67.294,13.788 67.646,14.024 68.129,14.024C68.165,14.028 68.201,14.029 68.236,14.029C68.792,14.029 69.258,13.594 69.295,13.04Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M71.348,12.444C71.348,11.021 72.08,10.12 73.217,10.12C73.791,10.094 74.33,10.402 74.598,10.91L74.665,10.91L74.665,8.437L75.553,8.437L75.553,14.698L74.702,14.698L74.702,13.986L74.631,13.986C74.343,14.49 73.797,14.793 73.217,14.772C72.072,14.772 71.348,13.871 71.348,12.444ZM72.266,12.444C72.266,13.399 72.716,13.974 73.469,13.974C74.218,13.974 74.681,13.391 74.681,12.448C74.681,11.51 74.213,10.918 73.469,10.918C72.721,10.918 72.266,11.497 72.266,12.444L72.266,12.444Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M79.23,12.444C79.224,12.377 79.22,12.309 79.22,12.241C79.22,11.071 80.183,10.108 81.354,10.108C82.524,10.108 83.487,11.071 83.487,12.241C83.487,12.309 83.484,12.377 83.477,12.444C83.484,12.513 83.487,12.582 83.487,12.651C83.487,13.822 82.524,14.785 81.354,14.785C80.183,14.785 79.22,13.822 79.22,12.651C79.22,12.582 79.223,12.513 79.23,12.444ZM82.563,12.444C82.563,11.468 82.125,10.897 81.355,10.897C80.583,10.897 80.148,11.468 80.148,12.444C80.148,13.428 80.583,13.995 81.355,13.995C82.125,13.995 82.563,13.424 82.563,12.444Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M84.669,10.195L85.525,10.195L85.525,10.91L85.591,10.91C85.822,10.385 86.363,10.061 86.935,10.108C86.972,10.105 87.008,10.104 87.045,10.104C87.848,10.104 88.509,10.765 88.509,11.568C88.509,11.64 88.504,11.712 88.494,11.783L88.494,14.698L87.605,14.698L87.605,12.006C87.605,11.282 87.291,10.922 86.633,10.922C86.617,10.922 86.601,10.921 86.585,10.921C86.019,10.921 85.552,11.388 85.552,11.954C85.552,11.991 85.554,12.027 85.558,12.063L85.558,14.698L84.669,14.698L84.669,10.195Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M93.515,9.074L93.515,10.215L94.491,10.215L94.491,10.964L93.515,10.964L93.515,13.279C93.515,13.751 93.709,13.958 94.152,13.958C94.265,13.957 94.378,13.95 94.491,13.937L94.491,14.677C94.331,14.706 94.169,14.721 94.007,14.723C93.019,14.723 92.626,14.375 92.626,13.507L92.626,10.964L91.911,10.964L91.911,10.215L92.626,10.215L92.626,9.074L93.515,9.074Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M95.705,8.437L96.585,8.437L96.585,10.918L96.656,10.918C96.897,10.388 97.448,10.065 98.029,10.112C98.056,10.11 98.082,10.11 98.109,10.11C98.923,10.11 99.593,10.779 99.593,11.593C99.593,11.659 99.588,11.725 99.58,11.791L99.58,14.698L98.69,14.698L98.69,12.01C98.69,11.291 98.355,10.926 97.727,10.926C97.699,10.924 97.67,10.923 97.641,10.923C97.064,10.923 96.589,11.398 96.589,11.975C96.589,12.006 96.591,12.037 96.593,12.068L96.593,14.698L95.705,14.698L95.705,8.437Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M104.761,13.482C104.513,14.328 103.687,14.88 102.81,14.785C102.792,14.785 102.774,14.785 102.756,14.785C101.634,14.785 100.711,13.862 100.711,12.74C100.711,12.647 100.717,12.553 100.73,12.46C100.718,12.369 100.712,12.277 100.712,12.185C100.712,11.045 101.649,10.108 102.788,10.108C102.794,10.108 102.8,10.108 102.806,10.108C104.059,10.108 104.815,10.964 104.815,12.378L104.815,12.688L101.635,12.688L101.635,12.738C101.632,12.771 101.631,12.804 101.631,12.838C101.631,13.491 102.168,14.028 102.821,14.028C102.826,14.028 102.83,14.028 102.834,14.028C103.268,14.08 103.693,13.864 103.906,13.482L104.761,13.482ZM101.635,12.031L103.91,12.031C103.912,12.004 103.913,11.977 103.913,11.95C103.913,11.354 103.422,10.864 102.826,10.864C102.818,10.864 102.81,10.864 102.801,10.864C102.796,10.864 102.792,10.864 102.787,10.864C102.155,10.864 101.635,11.384 101.635,12.016C101.635,12.021 101.635,12.026 101.635,12.031L101.635,12.031Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

27
.github/assets/badge-flathub.svg vendored Normal file
View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 300 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;">
<g transform="matrix(1,0,0,1,-348.1,-151.685)">
<path d="M646.159,168.627C646.159,159.796 638.99,152.627 630.159,152.627L365.042,152.627C356.211,152.627 349.042,159.796 349.042,168.627L349.042,234.41C349.042,243.241 356.211,250.41 365.042,250.41L630.159,250.41C638.99,250.41 646.159,243.241 646.159,234.41L646.159,168.627Z" style="stroke:rgb(136,138,133);stroke-width:1.88px;"/>
<g>
<path d="M464.084,188.646C467.784,188.646 469.925,186.351 469.925,182.556C469.925,178.778 467.785,176.501 464.209,176.501L460.153,176.501L460.153,188.646L464.084,188.646ZM461.985,187.045L461.985,178.102L464.096,178.102C466.753,178.102 468.123,179.692 468.123,182.556C468.123,185.432 466.753,187.045 463.983,187.045L461.985,187.045ZM478.644,188.83C481.212,188.83 482.89,186.95 482.89,184.133C482.89,181.299 481.212,179.419 478.644,179.419C476.077,179.419 474.398,181.299 474.398,184.133C474.398,186.95 476.077,188.83 478.644,188.83ZM478.65,187.341C476.972,187.341 476.19,185.877 476.19,184.127C476.19,182.384 476.972,180.901 478.65,180.901C480.317,180.901 481.1,182.384 481.1,184.127C481.1,185.877 480.317,187.341 478.65,187.341ZM489.308,188.646L491.111,188.646L492.961,182.07L493.097,182.07L494.947,188.646L496.757,188.646L499.431,179.537L497.598,179.537L495.825,186.197L495.736,186.197L493.957,179.537L492.125,179.537L490.334,186.227L490.245,186.227L488.46,179.537L486.628,179.537L489.308,188.646ZM505.63,183.238C505.63,181.785 506.519,180.955 507.752,180.955C508.956,180.955 509.685,181.743 509.685,183.065L509.685,188.645L511.458,188.645L511.458,182.852C511.458,180.599 510.219,179.419 508.358,179.419C506.988,179.419 506.092,180.053 505.671,181.019L505.558,181.019L505.558,179.537L503.856,179.537L503.856,188.646L505.629,188.646L505.63,183.238ZM518.35,176.501L516.578,176.501L516.578,188.646L518.351,188.646L518.35,176.501ZM527.319,188.83C529.887,188.83 531.565,186.95 531.565,184.133C531.565,181.299 529.887,179.419 527.319,179.419C524.751,179.419 523.073,181.299 523.073,184.133C523.073,186.95 524.751,188.83 527.319,188.83ZM527.325,187.341C525.647,187.341 524.864,185.877 524.864,184.127C524.864,182.384 525.647,180.901 527.324,180.901C528.991,180.901 529.774,182.384 529.774,184.127C529.774,185.877 528.991,187.341 527.324,187.341L527.325,187.341ZM538.937,188.848C540.444,188.848 541.292,188.083 541.63,187.401L541.7,187.401L541.7,188.646L543.432,188.646L543.432,182.597C543.432,179.947 541.345,179.419 539.898,179.419C538.25,179.419 536.732,180.083 536.138,181.743L537.805,182.123C538.065,181.477 538.73,180.853 539.922,180.853C541.066,180.853 541.653,181.453 541.653,182.485L541.653,182.526C541.653,183.173 540.989,183.161 539.353,183.35C537.627,183.552 535.86,184.003 535.86,186.072C535.86,187.863 537.206,188.848 538.938,188.848L538.937,188.848ZM539.323,187.424C538.321,187.424 537.597,186.974 537.597,186.096C537.597,185.147 538.439,184.809 539.465,184.673C540.04,184.596 541.405,184.442 541.659,184.187L541.659,185.361C541.659,186.44 540.799,187.424 539.323,187.424ZM551.95,188.824C553.61,188.824 554.262,187.81 554.583,187.229L554.731,187.229L554.731,188.646L556.462,188.646L556.462,176.5L554.689,176.5L554.689,181.013L554.583,181.013C554.263,180.45 553.658,179.418 551.962,179.418C549.762,179.418 548.142,181.155 548.142,184.108C548.142,187.056 549.738,188.823 551.95,188.823L551.95,188.824ZM552.341,187.312C550.758,187.312 549.933,185.918 549.933,184.092C549.933,182.283 550.74,180.925 552.341,180.925C553.889,180.925 554.719,182.188 554.719,184.092C554.719,186.007 553.871,187.312 552.341,187.312ZM572.744,188.83C575.312,188.83 576.99,186.95 576.99,184.133C576.99,181.299 575.312,179.419 572.744,179.419C570.176,179.419 568.498,181.299 568.498,184.133C568.498,186.95 570.176,188.83 572.744,188.83ZM572.75,187.341C571.072,187.341 570.289,185.877 570.289,184.127C570.289,182.384 571.072,180.901 572.749,180.901C574.416,180.901 575.199,182.384 575.199,184.127C575.199,185.877 574.416,187.341 572.749,187.341L572.75,187.341ZM583.485,183.238C583.485,181.785 584.375,180.955 585.608,180.955C586.812,180.955 587.541,181.743 587.541,183.065L587.541,188.645L589.314,188.645L589.314,182.852C589.314,180.599 588.074,179.419 586.213,179.419C584.843,179.419 583.947,180.053 583.526,181.019L583.414,181.019L583.414,179.537L581.712,179.537L581.712,188.646L583.485,188.646L583.485,183.238Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<g>
<path d="M460.153,222.645L464.983,222.645L464.983,211.32L476.06,211.32L476.06,207.272L464.982,207.272L464.982,200.034L477.232,200.034L477.232,195.986L460.152,195.986L460.153,222.645Z" style="fill:white;fill-rule:nonzero;"/>
<rect x="481.41" y="195.986" width="4.712" height="26.66" style="fill:white;fill-rule:nonzero;"/>
<path d="M496.718,223.049C499.855,223.049 501.73,221.578 502.588,219.899L502.745,219.899L502.745,222.645L507.275,222.645L507.275,209.263C507.275,203.978 502.966,202.39 499.152,202.39C494.948,202.39 491.719,204.265 490.678,207.91L495.078,208.535C495.546,207.168 496.874,205.996 499.178,205.996C501.365,205.996 502.563,207.116 502.563,209.081L502.563,209.159C502.563,210.513 501.143,210.579 497.616,210.956C493.737,211.372 490.027,212.531 490.027,217.035C490.027,220.965 492.904,223.049 496.718,223.049ZM497.942,219.586C495.976,219.586 494.57,218.688 494.57,216.956C494.57,215.147 496.145,214.392 498.254,214.093C499.491,213.923 501.964,213.611 502.576,213.117L502.576,215.473C502.576,217.699 500.779,219.586 497.942,219.586Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M522.01,202.65L518.066,202.65L518.066,197.86L513.354,197.86L513.354,202.65L510.516,202.65L510.516,206.296L513.354,206.296L513.354,217.412C513.328,221.174 516.062,223.022 519.602,222.918C520.943,222.879 521.867,222.619 522.375,222.45L521.581,218.766C521.321,218.831 520.787,218.948 520.201,218.948C519.016,218.948 518.066,218.532 518.066,216.631L518.066,206.296L522.01,206.296L522.01,202.65Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M531.083,210.93C531.083,208.04 532.88,206.374 535.405,206.374C537.878,206.374 539.336,207.949 539.336,210.644L539.336,222.645L544.049,222.645L544.049,209.915C544.049,205.085 541.315,202.39 537.162,202.39C534.09,202.39 532.138,203.783 531.214,206.048L530.979,206.048L530.979,195.986L526.371,195.986L526.371,222.646L531.083,222.646L531.083,210.93Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M561.583,214.236C561.583,217.282 559.409,218.792 557.326,218.792C555.061,218.792 553.551,217.191 553.551,214.652L553.551,202.651L548.839,202.651L548.839,215.381C548.839,220.185 551.572,222.905 555.504,222.905C558.498,222.905 560.606,221.33 561.518,219.091L561.726,219.091L561.726,222.645L566.295,222.645L566.295,202.651L561.583,202.651L561.583,214.236Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M571.346,222.645L575.98,222.645L575.98,219.495L576.253,219.495C576.995,220.953 578.544,222.997 581.981,222.997C586.693,222.997 590.221,219.261 590.221,212.674C590.221,206.009 586.589,202.39 581.968,202.39C578.44,202.39 576.969,204.512 576.253,205.957L576.058,205.957L576.058,195.986L571.346,195.986L571.346,222.645ZM575.966,212.648C575.966,208.768 577.633,206.256 580.666,206.256C583.803,206.256 585.417,208.925 585.417,212.648C585.417,216.397 583.777,219.13 580.666,219.13C577.659,219.13 575.966,216.527 575.966,212.648Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(1.24662,0,0,1.24662,192.661,67.896)">
<circle cx="166.688" cy="95.647" r="9.048" style="fill:white;"/>
<path d="M174.826,111.309C174.826,109.371 173.253,107.798 171.315,107.798L161.925,107.798C159.987,107.798 158.414,109.371 158.414,111.309L158.414,120.699C158.414,122.637 159.987,124.21 161.925,124.21L171.315,124.21C173.253,124.21 174.826,122.637 174.826,120.699L174.826,111.309Z" style="fill:white;"/>
<g transform="matrix(0.925902,0.53457,0.53457,-0.925902,99.8266,110.693)">
<path d="M69.514,58.833L57.486,58.833C56.614,58.833 55.805,58.366 55.369,57.611C54.933,56.856 54.933,55.922 55.369,55.167L56.259,53.625L61.383,44.75C61.819,43.994 62.628,43.527 63.5,43.527C64.372,43.527 65.181,43.994 65.617,44.75L66.507,46.292L71.631,55.167C72.067,55.922 72.067,56.856 71.631,57.611C71.195,58.366 70.386,58.833 69.514,58.833Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<path d="M194.992,116.11C194.992,116.99 194.284,117.697 193.404,117.697L180.704,117.697C179.824,117.697 179.117,116.989 179.117,116.11C179.117,115.23 179.825,114.522 180.704,114.522L193.404,114.522C194.284,114.522 194.992,115.23 194.992,116.11ZM187.054,108.172C187.934,108.172 188.642,108.88 188.642,109.76L188.642,122.46C188.642,123.34 187.934,124.047 187.054,124.047C186.174,124.047 185.467,123.339 185.467,122.46L185.467,109.76C185.467,108.88 186.175,108.172 187.054,108.172Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

25
.github/assets/badge-google-play.svg vendored Normal file
View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 563 167" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-miterlimit:2;">
<g transform="matrix(4.16667,0,0,4.16667,0,-4)">
<g>
<g>
<path d="M130,41L4.999,41C2.249,41 0,38.75 0,36L0,6C0,3.25 2.249,1 4.999,1L130,1C132.75,1 135,3.25 135,6L135,36C135,38.75 132.75,41 130,41Z" style="fill:rgb(3,4,4);fill-rule:nonzero;"/>
<path d="M130,1L4.999,1C2.249,1 0,3.25 0,6L0,36C0,38.75 2.249,41 4.999,41L130,41C132.75,41 135,38.75 135,36L135,6C135,3.25 132.75,1 130,1ZM130,1.8C132.316,1.8 134.2,3.685 134.2,6L134.2,36C134.2,38.316 132.316,40.201 130,40.201L4.999,40.201C2.684,40.201 0.8,38.316 0.8,36L0.8,6C0.8,3.685 2.684,1.8 4.999,1.8L130,1.8Z" style="fill:rgb(167,165,166);fill-rule:nonzero;"/>
<path d="M47.376,10.791L44.468,10.791L44.468,11.512L46.647,11.512C46.588,12.098 46.353,12.559 45.96,12.894C45.566,13.229 45.063,13.397 44.468,13.397C43.814,13.397 43.261,13.171 42.809,12.718C42.365,12.257 42.138,11.688 42.138,11C42.138,10.313 42.365,9.743 42.809,9.282C43.261,8.83 43.814,8.604 44.468,8.604C44.803,8.604 45.122,8.662 45.415,8.788C45.708,8.914 45.943,9.09 46.127,9.316L46.68,8.763C46.429,8.478 46.11,8.26 45.717,8.101C45.323,7.942 44.912,7.866 44.468,7.866C43.596,7.866 42.859,8.168 42.256,8.771C41.652,9.375 41.351,10.12 41.351,11C41.351,11.88 41.652,12.626 42.256,13.229C42.859,13.833 43.596,14.134 44.468,14.134C45.381,14.134 46.11,13.841 46.672,13.246C47.166,12.752 47.418,12.081 47.418,11.243C47.418,11.101 47.401,10.95 47.376,10.791Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M48.524,8L48.524,14L52.027,14L52.027,13.263L49.295,13.263L49.295,11.361L51.758,11.361L51.758,10.64L49.295,10.64L49.295,8.738L52.027,8.738L52.027,8L48.524,8Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M56.953,8.738L56.953,8L52.83,8L52.83,8.738L54.506,8.738L54.506,14L55.277,14L55.277,8.738L56.953,8.738Z" style="fill:white;fill-rule:nonzero;"/>
<rect x="59.937" y="8" width="0.771" height="6" style="fill:white;"/>
<path d="M65.803,8.738L65.803,8L61.68,8L61.68,8.738L63.356,8.738L63.356,14L64.127,14L64.127,8.738L65.803,8.738Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M73.605,8.78C73.01,8.168 72.281,7.866 71.409,7.866C70.538,7.866 69.808,8.168 69.213,8.771C68.618,9.366 68.325,10.112 68.325,11C68.325,11.889 68.618,12.634 69.213,13.229C69.808,13.833 70.538,14.134 71.409,14.134C72.272,14.134 73.01,13.833 73.605,13.229C74.2,12.634 74.493,11.889 74.493,11C74.493,10.12 74.2,9.375 73.605,8.78ZM69.767,9.282C70.211,8.83 70.755,8.604 71.409,8.604C72.063,8.604 72.607,8.83 73.043,9.282C73.487,9.727 73.705,10.305 73.705,11C73.705,11.696 73.487,12.274 73.043,12.718C72.607,13.171 72.063,13.397 71.409,13.397C70.755,13.397 70.211,13.171 69.767,12.718C69.331,12.266 69.113,11.696 69.113,11C69.113,10.305 69.331,9.735 69.767,9.282Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M76.345,10.263L76.312,9.106L76.345,9.106L79.396,14L80.2,14L80.2,8L79.429,8L79.429,11.512L79.463,12.668L79.429,12.668L76.513,8L75.575,8L75.575,14L76.345,14L76.345,10.263Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M47.376,10.791L44.468,10.791L44.468,11.512L46.647,11.512C46.588,12.098 46.353,12.559 45.96,12.894C45.566,13.229 45.063,13.397 44.468,13.397C43.814,13.397 43.261,13.171 42.809,12.718C42.365,12.257 42.138,11.688 42.138,11C42.138,10.313 42.365,9.743 42.809,9.282C43.261,8.83 43.814,8.604 44.468,8.604C44.803,8.604 45.122,8.662 45.415,8.788C45.708,8.914 45.943,9.09 46.127,9.316L46.68,8.763C46.429,8.478 46.11,8.26 45.717,8.101C45.323,7.942 44.912,7.866 44.468,7.866C43.596,7.866 42.859,8.168 42.256,8.771C41.652,9.375 41.351,10.12 41.351,11C41.351,11.88 41.652,12.626 42.256,13.229C42.859,13.833 43.596,14.134 44.468,14.134C45.381,14.134 46.11,13.841 46.672,13.246C47.166,12.752 47.418,12.081 47.418,11.243C47.418,11.101 47.401,10.95 47.376,10.791ZM48.524,8L48.524,14L52.027,14L52.027,13.263L49.295,13.263L49.295,11.361L51.758,11.361L51.758,10.64L49.295,10.64L49.295,8.738L52.027,8.738L52.027,8L48.524,8ZM56.953,8.738L56.953,8L52.831,8L52.831,8.738L54.507,8.738L54.507,14L55.277,14L55.277,8.738L56.953,8.738ZM60.708,8L59.937,8L59.937,14L60.708,14L60.708,8ZM65.803,8.738L65.803,8L61.68,8L61.68,8.738L63.356,8.738L63.356,14L64.127,14L64.127,8.738L65.803,8.738ZM73.605,8.78C73.01,8.168 72.281,7.866 71.409,7.866C70.537,7.866 69.808,8.168 69.213,8.771C68.618,9.366 68.325,10.112 68.325,11C68.325,11.889 68.618,12.634 69.213,13.229C69.808,13.833 70.537,14.134 71.409,14.134C72.272,14.134 73.01,13.833 73.605,13.229C74.2,12.634 74.493,11.889 74.493,11C74.493,10.12 74.2,9.375 73.605,8.78ZM69.767,9.282C70.211,8.83 70.755,8.604 71.409,8.604C72.063,8.604 72.607,8.83 73.043,9.282C73.487,9.727 73.705,10.305 73.705,11C73.705,11.696 73.487,12.274 73.043,12.718C72.607,13.171 72.063,13.397 71.409,13.397C70.755,13.397 70.211,13.171 69.767,12.718C69.331,12.266 69.113,11.696 69.113,11C69.113,10.305 69.331,9.735 69.767,9.282ZM76.346,10.263L76.312,9.106L76.346,9.106L79.396,14L80.2,14L80.2,8L79.429,8L79.429,11.512L79.463,12.668L79.429,12.668L76.513,8L75.575,8L75.575,14L76.346,14L76.346,10.263Z" style="fill:none;stroke:white;stroke-width:0.2px;"/>
<path d="M106.936,31.001L108.802,31.001L108.802,18.499L106.936,18.499L106.936,31.001ZM123.743,23.002L121.604,28.422L121.54,28.422L119.32,23.002L117.31,23.002L120.64,30.578L118.741,34.791L120.687,34.791L125.818,23.002L123.743,23.002ZM113.16,29.581C112.55,29.581 111.697,29.275 111.697,28.519C111.697,27.554 112.759,27.184 113.675,27.184C114.495,27.184 114.882,27.361 115.38,27.602C115.235,28.76 114.238,29.581 113.16,29.581ZM113.386,22.729C112.035,22.729 110.636,23.324 110.057,24.643L111.713,25.334C112.067,24.643 112.726,24.418 113.418,24.418C114.383,24.418 115.364,24.997 115.38,26.026L115.38,26.155C115.042,25.962 114.318,25.672 113.434,25.672C111.648,25.672 109.831,26.653 109.831,28.487C109.831,30.16 111.295,31.237 112.935,31.237C114.189,31.237 114.882,30.674 115.315,30.015L115.38,30.015L115.38,30.98L117.182,30.98L117.182,26.187C117.182,23.967 115.524,22.729 113.386,22.729ZM101.854,24.524L99.2,24.524L99.2,20.239L101.854,20.239C103.249,20.239 104.041,21.394 104.041,22.382C104.041,23.351 103.249,24.524 101.854,24.524ZM101.806,18.499L97.334,18.499L97.334,31.001L99.2,31.001L99.2,26.264L101.806,26.264C103.874,26.264 105.907,24.767 105.907,22.382C105.907,19.997 103.874,18.499 101.806,18.499ZM77.424,29.583C76.135,29.583 75.056,28.503 75.056,27.022C75.056,25.523 76.135,24.428 77.424,24.428C78.697,24.428 79.696,25.523 79.696,27.022C79.696,28.503 78.697,29.583 77.424,29.583ZM79.567,23.703L79.502,23.703C79.083,23.203 78.278,22.752 77.263,22.752C75.136,22.752 73.187,24.621 73.187,27.022C73.187,29.406 75.136,31.258 77.263,31.258C78.278,31.258 79.083,30.807 79.502,30.292L79.567,30.292L79.567,30.904C79.567,32.531 78.697,33.401 77.295,33.401C76.152,33.401 75.443,32.58 75.153,31.887L73.526,32.563C73.993,33.691 75.233,35.077 77.295,35.077C79.487,35.077 81.339,33.788 81.339,30.646L81.339,23.01L79.567,23.01L79.567,23.703ZM82.628,31.001L84.497,31.001L84.497,18.499L82.628,18.499L82.628,31.001ZM87.251,26.876C87.204,25.233 88.525,24.396 89.475,24.396C90.216,24.396 90.844,24.766 91.054,25.297L87.251,26.876ZM93.051,25.459C92.697,24.508 91.618,22.752 89.411,22.752C87.219,22.752 85.399,24.476 85.399,27.005C85.399,29.39 87.204,31.258 89.62,31.258C91.569,31.258 92.697,30.066 93.165,29.374L91.714,28.407C91.231,29.116 90.571,29.583 89.62,29.583C88.669,29.583 87.993,29.148 87.558,28.294L93.245,25.942L93.051,25.459ZM47.743,24.057L47.743,25.861L52.061,25.861C51.932,26.876 51.594,27.617 51.078,28.133C50.45,28.761 49.467,29.454 47.743,29.454C45.085,29.454 43.007,27.312 43.007,24.653C43.007,21.995 45.085,19.852 47.743,19.852C49.177,19.852 50.224,20.416 50.998,21.141L52.27,19.868C51.191,18.837 49.757,18.048 47.743,18.048C44.102,18.048 41.041,21.012 41.041,24.653C41.041,28.294 44.102,31.258 47.743,31.258C49.708,31.258 51.191,30.614 52.351,29.406C53.543,28.213 53.914,26.538 53.914,25.185C53.914,24.766 53.881,24.379 53.817,24.057L47.743,24.057ZM58.822,29.583C57.533,29.583 56.421,28.52 56.421,27.005C56.421,25.475 57.533,24.428 58.822,24.428C60.111,24.428 61.223,25.475 61.223,27.005C61.223,28.52 60.111,29.583 58.822,29.583ZM58.822,22.752C56.47,22.752 54.553,24.541 54.553,27.005C54.553,29.454 56.47,31.258 58.822,31.258C61.174,31.258 63.091,29.454 63.091,27.005C63.091,24.541 61.174,22.752 58.822,22.752ZM68.135,29.583C66.847,29.583 65.735,28.52 65.735,27.005C65.735,25.475 66.847,24.428 68.135,24.428C69.424,24.428 70.536,25.475 70.536,27.005C70.536,28.52 69.424,29.583 68.135,29.583ZM68.135,22.752C65.783,22.752 63.866,24.541 63.866,27.005C63.866,29.454 65.783,31.258 68.135,31.258C70.488,31.258 72.405,29.454 72.405,27.005C72.405,24.541 70.488,22.752 68.135,22.752Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M20.717,20.425L10.07,31.725C10.071,31.727 10.071,31.729 10.072,31.731C10.398,32.959 11.519,33.862 12.849,33.862C13.381,33.862 13.88,33.718 14.308,33.466L14.342,33.446L26.326,26.531L20.717,20.425Z" style="fill:rgb(235,67,53);fill-rule:nonzero;"/>
<path d="M31.488,18.501L31.478,18.494L26.304,15.494L20.475,20.681L26.324,26.529L31.471,23.56C32.373,23.073 32.985,22.122 32.985,21.025C32.985,19.936 32.381,18.989 31.488,18.501Z" style="fill:rgb(250,188,19);fill-rule:nonzero;"/>
<path d="M10.07,10.278C10.006,10.514 9.972,10.761 9.972,11.018L9.972,30.985C9.972,31.242 10.005,31.49 10.07,31.725L21.083,20.714L10.07,10.278Z" style="fill:rgb(84,125,191);fill-rule:nonzero;"/>
<path d="M20.795,21.001L26.306,15.492L14.335,8.552C13.9,8.291 13.393,8.141 12.849,8.141C11.519,8.141 10.397,9.046 10.07,10.275L10.07,10.278L20.795,21.001Z" style="fill:rgb(48,168,81);fill-rule:nonzero;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

52
.github/assets/badge-mac-app-store.svg vendored Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 157 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g>
<g>
<g>
<path d="M146.571,0L9.535,0C9.168,0 8.806,0 8.44,0.002C8.134,0.004 7.83,0.01 7.521,0.015C6.85,0.023 6.18,0.082 5.517,0.191C4.856,0.304 4.215,0.515 3.616,0.818C3.019,1.124 2.472,1.522 1.998,1.997C1.52,2.471 1.122,3.018 0.819,3.618C0.515,4.217 0.305,4.859 0.194,5.521C0.083,6.183 0.023,6.853 0.015,7.523C0.006,7.83 0.005,8.138 0,8.444L0,31.559C0.005,31.869 0.006,32.17 0.015,32.481C0.023,33.151 0.083,33.821 0.194,34.482C0.304,35.145 0.515,35.788 0.819,36.387C1.122,36.985 1.52,37.53 1.998,38.001C2.471,38.478 3.017,38.876 3.616,39.18C4.215,39.484 4.855,39.697 5.517,39.811C6.18,39.919 6.85,39.978 7.521,39.987C7.83,39.994 8.134,39.998 8.44,39.998C8.806,40 9.168,40 9.535,40L146.571,40C146.931,40 147.296,40 147.655,39.998C147.96,39.998 148.272,39.994 148.577,39.987C149.247,39.979 149.916,39.92 150.577,39.81C151.241,39.696 151.884,39.483 152.485,39.18C153.084,38.876 153.63,38.478 154.103,38.001C154.579,37.528 154.977,36.983 155.284,36.387C155.586,35.787 155.795,35.145 155.903,34.482C156.015,33.821 156.077,33.151 156.089,32.481C156.093,32.17 156.093,31.869 156.093,31.559C156.101,31.195 156.101,30.834 156.101,30.465L156.101,9.536C156.101,9.17 156.101,8.807 156.093,8.444C156.093,8.138 156.093,7.83 156.089,7.523C156.077,6.852 156.015,6.183 155.903,5.521C155.795,4.859 155.586,4.217 155.284,3.618C154.667,2.415 153.688,1.436 152.485,0.818C151.884,0.516 151.241,0.304 150.577,0.191C149.916,0.081 149.247,0.022 148.577,0.015C148.272,0.01 147.96,0.004 147.655,0.002C147.296,-0 146.931,-0 146.571,-0L146.571,0Z" style="fill:rgb(166,166,166);fill-rule:nonzero;"/>
<path d="M8.445,39.125C8.14,39.125 7.843,39.121 7.541,39.114C6.914,39.106 6.29,39.052 5.671,38.951C5.095,38.852 4.537,38.667 4.015,38.403C3.498,38.142 3.026,37.798 2.618,37.387C2.204,36.98 1.859,36.508 1.597,35.99C1.333,35.469 1.149,34.91 1.054,34.333C0.951,33.713 0.896,33.086 0.888,32.458C0.881,32.247 0.873,31.545 0.873,31.545L0.873,8.444C0.873,8.444 0.882,7.753 0.888,7.55C0.895,6.922 0.951,6.297 1.053,5.678C1.149,5.099 1.332,4.539 1.597,4.016C1.857,3.498 2.2,3.026 2.612,2.618C3.023,2.206 3.496,1.861 4.014,1.595C4.535,1.332 5.092,1.149 5.667,1.051C6.288,0.95 6.915,0.895 7.543,0.887L8.445,0.875L147.65,0.875L148.563,0.888C149.186,0.895 149.807,0.949 150.422,1.05C151.003,1.149 151.566,1.334 152.093,1.598C153.13,2.133 153.975,2.979 154.508,4.018C154.768,4.538 154.949,5.094 155.043,5.667C155.147,6.291 155.205,6.922 155.217,7.554C155.22,7.837 155.22,8.142 155.22,8.444C155.228,8.819 155.228,9.176 155.228,9.536L155.228,30.465C155.228,30.828 155.228,31.183 155.22,31.54C155.22,31.865 155.22,32.163 155.216,32.47C155.204,33.091 155.147,33.71 155.045,34.323C154.952,34.904 154.769,35.468 154.505,35.993C154.241,36.506 153.898,36.973 153.489,37.379C153.081,37.793 152.608,38.138 152.09,38.401C151.565,38.667 151.002,38.853 150.422,38.951C149.804,39.052 149.179,39.107 148.553,39.114C148.26,39.121 147.953,39.125 147.655,39.125L146.571,39.127L8.445,39.125Z" style="fill-rule:nonzero;"/>
</g>
<g id="_Group_">
<g id="_Group_2_" serif:id="_Group_2">
<g id="_Group_3_" serif:id="_Group_3">
<g id="_Group_4_" serif:id="_Group_4">
<path id="_Path_" d="M24.769,20.301C24.791,18.606 25.682,17.036 27.125,16.149C26.21,14.842 24.729,14.041 23.134,13.991C21.455,13.815 19.827,14.996 18.971,14.996C18.099,14.996 16.782,14.008 15.363,14.038C13.498,14.098 11.797,15.135 10.89,16.766C8.956,20.114 10.399,25.035 12.251,27.742C13.178,29.067 14.261,30.547 15.679,30.495C17.066,30.437 17.584,29.61 19.258,29.61C20.917,29.61 21.403,30.495 22.849,30.462C24.338,30.437 25.275,29.13 26.17,27.792C26.836,26.848 27.348,25.804 27.688,24.7C25.924,23.954 24.771,22.216 24.769,20.301Z" style="fill:white;fill-rule:nonzero;"/>
<path id="_Path_2_" serif:id="_Path_2" d="M22.037,12.211C22.848,11.237 23.249,9.984 23.152,8.72C21.912,8.85 20.766,9.443 19.944,10.38C19.132,11.304 18.721,12.514 18.8,13.741C20.056,13.754 21.25,13.189 22.037,12.211Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</g>
<g>
<path d="M46.149,30.496L46.149,21.356L46.088,21.356L42.345,30.401L40.917,30.401L37.164,21.356L37.104,21.356L37.104,30.496L35.348,30.496L35.348,18.078L37.578,18.078L41.596,27.88L41.665,27.88L45.675,18.078L47.913,18.078L47.913,30.496L46.149,30.496Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M49.396,27.923C49.396,26.34 50.609,25.384 52.761,25.255L55.24,25.117L55.24,24.429C55.24,23.422 54.577,22.853 53.449,22.853C52.588,22.739 51.768,23.289 51.547,24.128L49.809,24.128C49.861,22.492 51.384,21.331 53.501,21.331C55.661,21.331 57.089,22.51 57.089,24.291L57.089,30.496L55.308,30.496L55.308,29.007L55.265,29.007C54.685,30.034 53.587,30.666 52.408,30.651C52.319,30.66 52.23,30.664 52.14,30.664C50.636,30.664 49.398,29.427 49.396,27.923ZM55.24,27.105L55.24,26.408L53.01,26.546C51.9,26.615 51.272,27.097 51.272,27.871C51.272,28.663 51.926,29.18 52.924,29.18C52.973,29.183 53.022,29.185 53.071,29.185C54.227,29.185 55.191,28.261 55.24,27.105L55.24,27.105Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M64.893,24.558C64.726,23.536 63.791,22.805 62.759,22.889C61.331,22.889 60.384,24.085 60.384,25.97C60.384,27.897 61.339,29.059 62.776,29.059C63.795,29.161 64.729,28.443 64.893,27.433L66.683,27.433C66.453,29.367 64.699,30.787 62.759,30.608C60.177,30.608 58.491,28.844 58.491,25.97C58.491,23.155 60.177,21.331 62.742,21.331C64.696,21.165 66.451,22.608 66.667,24.558L64.893,24.558Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M78.759,27.14L74.026,27.14L72.889,30.496L70.884,30.496L75.368,18.078L77.451,18.078L81.934,30.496L79.895,30.496L78.759,27.14ZM74.516,25.591L78.268,25.591L76.419,20.144L76.367,20.144L74.516,25.591Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M91.617,25.97C91.617,28.783 90.111,30.591 87.838,30.591C86.666,30.652 85.556,30.035 84.99,29.007L84.947,29.007L84.947,33.491L83.088,33.491L83.088,21.442L84.887,21.442L84.887,22.948L84.921,22.948C85.513,21.926 86.623,21.31 87.804,21.348C90.102,21.348 91.617,23.164 91.617,25.97ZM89.707,25.97C89.707,24.137 88.759,22.932 87.314,22.932C85.894,22.932 84.939,24.162 84.939,25.97C84.939,27.794 85.894,29.016 87.314,29.016C88.759,29.016 89.707,27.819 89.707,25.97Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M101.582,25.97C101.582,28.783 100.076,30.591 97.803,30.591C96.631,30.652 95.521,30.035 94.955,29.007L94.912,29.007L94.912,33.491L93.053,33.491L93.053,21.442L94.852,21.442L94.852,22.948L94.886,22.948C95.478,21.926 96.588,21.31 97.769,21.348C100.067,21.348 101.582,23.164 101.582,25.97ZM99.671,25.97C99.671,24.137 98.724,22.932 97.279,22.932C95.859,22.932 94.904,24.162 94.904,25.97C94.904,27.794 95.859,29.016 97.279,29.016C98.724,29.016 99.671,27.819 99.671,25.97L99.671,25.97Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M108.168,27.036C108.305,28.268 109.502,29.076 111.136,29.076C112.703,29.076 113.83,28.268 113.83,27.157C113.83,26.193 113.15,25.616 111.541,25.221L109.931,24.833C107.651,24.282 106.592,23.216 106.592,21.485C106.592,19.343 108.459,17.871 111.111,17.871C113.735,17.871 115.534,19.343 115.594,21.485L113.718,21.485C113.606,20.246 112.582,19.498 111.084,19.498C109.587,19.498 108.563,20.255 108.563,21.356C108.563,22.234 109.217,22.751 110.818,23.146L112.186,23.482C114.734,24.085 115.792,25.108 115.792,26.925C115.792,29.248 113.942,30.703 110.999,30.703C108.245,30.703 106.385,29.282 106.265,27.036L108.168,27.036Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M119.803,19.3L119.803,21.442L121.525,21.442L121.525,22.914L119.803,22.914L119.803,27.905C119.803,28.681 120.148,29.042 120.905,29.042C121.109,29.038 121.313,29.024 121.516,28.999L121.516,30.462C121.176,30.525 120.83,30.554 120.484,30.548C118.651,30.548 117.936,29.859 117.936,28.103L117.936,22.914L116.62,22.914L116.62,21.442L117.936,21.442L117.936,19.3L119.803,19.3Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M122.521,25.97C122.521,23.121 124.199,21.331 126.815,21.331C129.44,21.331 131.11,23.121 131.11,25.97C131.11,28.826 129.449,30.608 126.815,30.608C124.182,30.608 122.521,28.826 122.521,25.97ZM129.216,25.97C129.216,24.016 128.321,22.862 126.815,22.862C125.309,22.862 124.414,24.024 124.414,25.97C124.414,27.932 125.309,29.076 126.815,29.076C128.321,29.076 129.216,27.932 129.216,25.97L129.216,25.97Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M132.643,21.442L134.416,21.442L134.416,22.983L134.459,22.983C134.705,21.995 135.618,21.309 136.636,21.348C136.85,21.347 137.064,21.37 137.273,21.417L137.273,23.155C137.003,23.073 136.721,23.035 136.438,23.043C136.413,23.042 136.387,23.041 136.362,23.041C135.335,23.041 134.489,23.887 134.489,24.914C134.489,24.985 134.493,25.056 134.501,25.126L134.501,30.496L132.643,30.496L132.643,21.442Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M145.84,27.837C145.59,29.48 143.99,30.608 141.942,30.608C139.308,30.608 137.673,28.844 137.673,26.013C137.673,23.173 139.317,21.331 141.864,21.331C144.369,21.331 145.944,23.052 145.944,25.797L145.944,26.434L139.549,26.434L139.549,26.546C139.543,26.615 139.54,26.684 139.54,26.754C139.54,28.047 140.605,29.112 141.898,29.112C141.927,29.112 141.956,29.111 141.985,29.11C142.884,29.195 143.738,28.675 144.076,27.837L145.84,27.837ZM139.558,25.135L144.084,25.135C144.087,25.094 144.088,25.054 144.088,25.014C144.088,23.819 143.105,22.836 141.911,22.836C141.895,22.836 141.879,22.837 141.864,22.837C141.859,22.837 141.855,22.837 141.85,22.837C140.593,22.837 139.558,23.872 139.558,25.129C139.558,25.131 139.558,25.133 139.558,25.135L139.558,25.135Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</g>
</g>
</g>
<g id="_Group_5_" serif:id="_Group_5">
<g>
<path d="M37.826,8.731C37.889,8.726 37.952,8.724 38.015,8.724C39.463,8.724 40.655,9.916 40.655,11.364C40.655,11.475 40.648,11.586 40.634,11.696C40.634,13.602 39.604,14.698 37.826,14.698L35.671,14.698L35.671,8.731L37.826,8.731ZM36.598,13.854L37.723,13.854C37.76,13.856 37.797,13.857 37.835,13.857C38.864,13.857 39.71,13.011 39.71,11.981C39.71,11.89 39.704,11.799 39.69,11.708C39.702,11.623 39.708,11.538 39.708,11.452C39.708,10.42 38.859,9.571 37.827,9.571C37.792,9.571 37.757,9.572 37.723,9.574L36.598,9.574L36.598,13.854Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M41.681,12.444C41.674,12.377 41.671,12.309 41.671,12.241C41.671,11.071 42.634,10.108 43.804,10.108C44.974,10.108 45.937,11.071 45.937,12.241C45.937,12.309 45.934,12.377 45.928,12.444C45.934,12.513 45.938,12.582 45.938,12.651C45.938,13.822 44.975,14.785 43.804,14.785C42.634,14.785 41.671,13.822 41.671,12.651C41.671,12.582 41.674,12.513 41.681,12.444ZM45.014,12.444C45.014,11.468 44.575,10.897 43.806,10.897C43.033,10.897 42.599,11.468 42.599,12.444C42.599,13.428 43.033,13.995 43.806,13.995C44.575,13.995 45.014,13.424 45.014,12.444L45.014,12.444Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M51.573,14.698L50.651,14.698L49.721,11.381L49.65,11.381L48.724,14.698L47.811,14.698L46.569,10.195L47.471,10.195L48.277,13.631L48.344,13.631L49.27,10.195L50.122,10.195L51.048,13.631L51.118,13.631L51.921,10.195L52.81,10.195L51.573,14.698Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M53.854,10.195L54.709,10.195L54.709,10.91L54.775,10.91C55.006,10.385 55.547,10.061 56.119,10.108C56.156,10.105 56.192,10.104 56.229,10.104C57.032,10.104 57.694,10.765 57.694,11.568C57.694,11.64 57.688,11.712 57.678,11.783L57.678,14.698L56.789,14.698L56.789,12.006C56.789,11.282 56.475,10.922 55.817,10.922C55.801,10.922 55.785,10.921 55.769,10.921C55.203,10.921 54.736,11.388 54.736,11.954C54.736,11.991 54.738,12.027 54.742,12.063L54.742,14.698L53.854,14.698L53.854,10.195Z" style="fill:white;fill-rule:nonzero;"/>
<rect x="59.094" y="8.437" width="0.889" height="6.261" style="fill:white;fill-rule:nonzero;"/>
<path d="M61.218,12.444C61.211,12.377 61.208,12.309 61.208,12.241C61.208,11.071 62.171,10.108 63.341,10.108C64.512,10.108 65.475,11.071 65.475,12.241C65.475,12.309 65.471,12.377 65.465,12.444C65.472,12.513 65.475,12.582 65.475,12.651C65.475,13.822 64.512,14.785 63.341,14.785C62.171,14.785 61.208,13.822 61.208,12.651C61.208,12.582 61.211,12.513 61.218,12.444ZM64.551,12.444C64.551,11.468 64.112,10.897 63.343,10.897C62.57,10.897 62.136,11.468 62.136,12.444C62.136,13.428 62.57,13.995 63.343,13.995C64.112,13.995 64.551,13.424 64.551,12.444L64.551,12.444Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M66.4,13.424C66.4,12.614 67.004,12.146 68.075,12.08L69.295,12.01L69.295,11.621C69.295,11.146 68.98,10.877 68.373,10.877C67.877,10.877 67.533,11.059 67.435,11.377L66.574,11.377C66.665,10.604 67.393,10.108 68.414,10.108C69.543,10.108 70.18,10.67 70.18,11.621L70.18,14.698L69.324,14.698L69.324,14.065L69.254,14.065C68.964,14.526 68.446,14.797 67.901,14.772C67.855,14.777 67.808,14.779 67.761,14.779C67.016,14.779 66.403,14.169 66.4,13.424ZM69.295,13.04L69.295,12.663L68.195,12.733C67.575,12.775 67.294,12.986 67.294,13.383C67.294,13.788 67.646,14.024 68.129,14.024C68.164,14.028 68.2,14.029 68.236,14.029C68.791,14.029 69.257,13.594 69.295,13.04Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M71.348,12.444C71.348,11.021 72.079,10.12 73.217,10.12C73.79,10.094 74.33,10.402 74.598,10.91L74.664,10.91L74.664,8.437L75.553,8.437L75.553,14.698L74.701,14.698L74.701,13.986L74.631,13.986C74.343,14.49 73.797,14.793 73.217,14.772C72.071,14.772 71.348,13.871 71.348,12.444ZM72.266,12.444C72.266,13.399 72.716,13.974 73.469,13.974C74.218,13.974 74.681,13.391 74.681,12.448C74.681,11.51 74.213,10.918 73.469,10.918C72.721,10.918 72.266,11.497 72.266,12.444L72.266,12.444Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M79.23,12.444C79.223,12.377 79.22,12.309 79.22,12.241C79.22,11.071 80.183,10.108 81.353,10.108C82.524,10.108 83.487,11.071 83.487,12.241C83.487,12.309 83.484,12.377 83.477,12.444C83.484,12.513 83.487,12.582 83.487,12.651C83.487,13.821 82.524,14.785 81.353,14.785C80.183,14.785 79.219,13.821 79.219,12.651C79.219,12.582 79.223,12.513 79.23,12.444ZM82.563,12.444C82.563,11.468 82.124,10.897 81.355,10.897C80.582,10.897 80.148,11.468 80.148,12.444C80.148,13.428 80.582,13.995 81.355,13.995C82.124,13.995 82.563,13.424 82.563,12.444L82.563,12.444Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M84.669,10.195L85.525,10.195L85.525,10.91L85.591,10.91C85.822,10.385 86.363,10.061 86.935,10.108C86.972,10.105 87.008,10.104 87.045,10.104C87.848,10.104 88.509,10.765 88.509,11.568C88.509,11.64 88.504,11.712 88.494,11.783L88.494,14.698L87.605,14.698L87.605,12.006C87.605,11.282 87.291,10.922 86.633,10.922C86.617,10.922 86.601,10.921 86.585,10.921C86.019,10.921 85.552,11.388 85.552,11.954C85.552,11.991 85.554,12.027 85.558,12.063L85.558,14.698L84.669,14.698L84.669,10.195Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M93.515,9.074L93.515,10.215L94.491,10.215L94.491,10.964L93.515,10.964L93.515,13.279C93.515,13.751 93.709,13.958 94.152,13.958C94.265,13.957 94.378,13.95 94.491,13.937L94.491,14.677C94.331,14.706 94.169,14.721 94.007,14.723C93.019,14.723 92.626,14.375 92.626,13.507L92.626,10.964L91.911,10.964L91.911,10.215L92.626,10.215L92.626,9.074L93.515,9.074Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M95.705,8.437L96.585,8.437L96.585,10.918L96.656,10.918C96.897,10.388 97.448,10.065 98.029,10.112C98.056,10.11 98.082,10.11 98.109,10.11C98.923,10.11 99.593,10.779 99.593,11.593C99.593,11.659 99.588,11.725 99.58,11.791L99.58,14.698L98.69,14.698L98.69,12.01C98.69,11.291 98.355,10.926 97.727,10.926C97.699,10.924 97.67,10.923 97.641,10.923C97.064,10.923 96.589,11.398 96.589,11.975C96.589,12.006 96.591,12.037 96.593,12.068L96.593,14.698L95.705,14.698L95.705,8.437Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M104.761,13.482C104.513,14.328 103.687,14.88 102.81,14.785C102.792,14.785 102.774,14.785 102.756,14.785C101.634,14.785 100.711,13.862 100.711,12.74C100.711,12.647 100.717,12.553 100.73,12.46C100.718,12.369 100.712,12.277 100.712,12.185C100.712,11.045 101.649,10.108 102.788,10.108C102.794,10.108 102.8,10.108 102.806,10.108C104.059,10.108 104.815,10.964 104.815,12.378L104.815,12.688L101.635,12.688L101.635,12.738C101.632,12.771 101.631,12.804 101.631,12.838C101.631,13.491 102.168,14.028 102.821,14.028C102.826,14.028 102.83,14.028 102.834,14.028C103.268,14.08 103.693,13.864 103.906,13.482L104.761,13.482ZM101.635,12.031L103.91,12.031C103.912,12.004 103.913,11.977 103.913,11.95C103.913,11.354 103.422,10.864 102.826,10.864C102.818,10.864 102.81,10.864 102.801,10.864C102.796,10.864 102.792,10.864 102.787,10.864C102.155,10.864 101.635,11.384 101.635,12.016C101.635,12.021 101.635,12.026 101.635,12.031L101.635,12.031Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

23
.github/assets/badge-web.svg vendored Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 135 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<path d="M130.2,40L4.73,40C2.137,39.995 0.005,37.863 -0,35.27L0,4.73C-0,2.135 2.135,0 4.73,0L130.2,0C132.807,-0 134.962,2.123 135,4.73L135,35.27C134.957,37.875 132.805,39.995 130.2,40Z" style="fill:rgb(166,166,166);fill-rule:nonzero;"/>
<path d="M134,35.27C134,37.371 132.271,39.1 130.17,39.1L4.73,39.1C2.627,39.1 0.895,37.373 0.89,35.27L0.89,4.72C0.895,2.617 2.627,0.89 4.73,0.89L130.2,0.89C132.29,0.906 134,2.63 134,4.72L134,35.27Z" style="fill-rule:nonzero;"/>
<path d="M40.56,25.26L41.82,22.08L45.45,22.08L43.73,17.26L45.88,11.81L52.05,28.19L47.5,28.19L46.5,25.26L40.56,25.26Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M36.68,28.19L43.29,11.81L38.91,11.81L34.39,22.4L31.18,11.81L27.81,11.81L24.36,22.4L21.93,17.57L19.73,24.35L22,28.19L26.31,28.19L29.43,18.7L32.43,28.19L36.68,28.19Z" style="fill:rgb(90,15,200);fill-rule:nonzero;"/>
<path d="M12.7,22.57L15.4,22.57C16.136,22.582 16.871,22.488 17.58,22.29L18.28,20.14L20.23,14.14C20.08,13.902 19.91,13.678 19.72,13.47C18.57,12.302 16.965,11.695 15.33,11.81L8.55,11.81L8.55,28.19L12.7,28.19L12.7,22.57ZM16.27,15.57C16.674,15.994 16.888,16.565 16.86,17.15C16.892,17.723 16.706,18.288 16.34,18.73C15.77,19.23 15.014,19.466 14.26,19.38L12.7,19.38L12.7,15L14.27,15C14.987,14.922 15.706,15.13 16.27,15.58L16.27,15.57Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M61.25,14.45L61.25,8.74L61.91,8.74L61.91,13.85L64.43,13.85L64.43,14.45L61.25,14.45Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M67.94,14.45L67.81,13.84C67.645,14.069 67.43,14.258 67.18,14.39C66.925,14.489 66.653,14.536 66.38,14.53C66.017,14.55 65.66,14.432 65.38,14.2C65.131,13.957 64.999,13.617 65.02,13.27C65.02,12.4 65.71,11.95 67.1,11.91L67.82,11.91L67.82,11.64C67.842,11.376 67.768,11.113 67.61,10.9C67.421,10.725 67.167,10.637 66.91,10.66C66.489,10.68 66.076,10.789 65.7,10.98L65.5,10.49C65.719,10.366 65.955,10.275 66.2,10.22C66.444,10.152 66.697,10.119 66.95,10.12C67.359,10.087 67.766,10.208 68.09,10.46C68.358,10.757 68.492,11.151 68.46,11.55L68.46,14.47L67.94,14.45ZM66.47,14C66.836,14.03 67.198,13.906 67.47,13.66C67.712,13.413 67.839,13.075 67.82,12.73L67.82,12.35L67.17,12.35C66.783,12.339 66.399,12.422 66.05,12.59C65.827,12.738 65.697,12.993 65.71,13.26C65.696,13.459 65.773,13.654 65.92,13.79C66.075,13.918 66.269,13.992 66.47,14Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M70.36,10.17L70.36,13C70.337,13.281 70.423,13.56 70.6,13.78C70.801,13.964 71.068,14.058 71.34,14.04C71.712,14.077 72.081,13.94 72.34,13.67C72.576,13.317 72.685,12.893 72.65,12.47L72.65,10.17L73.3,10.17L73.3,14.45L72.76,14.45L72.67,13.88C72.539,14.092 72.348,14.259 72.12,14.36C71.866,14.476 71.589,14.534 71.31,14.53C70.887,14.564 70.467,14.431 70.14,14.16C69.841,13.85 69.682,13.43 69.7,13L69.7,10.2L70.36,10.17Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M77.59,14.45L77.59,11.68C77.613,11.399 77.527,11.12 77.35,10.9C77.149,10.716 76.882,10.622 76.61,10.64C76.238,10.603 75.869,10.74 75.61,11.01C75.37,11.361 75.26,11.786 75.3,12.21L75.3,14.45L74.65,14.45L74.65,10.17L75.18,10.17L75.28,10.76C75.41,10.545 75.602,10.374 75.83,10.27C76.079,10.148 76.353,10.087 76.63,10.09C77.055,10.059 77.475,10.195 77.8,10.47C78.09,10.795 78.232,11.226 78.19,11.66L78.19,14.45L77.59,14.45Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M81.28,14.53C80.746,14.573 80.219,14.379 79.84,14C79.474,13.543 79.292,12.965 79.33,12.38C79.294,11.782 79.479,11.191 79.85,10.72C80.231,10.314 80.774,10.098 81.33,10.13C81.535,10.134 81.739,10.157 81.94,10.2C82.11,10.23 82.275,10.284 82.43,10.36L82.23,10.91C82.077,10.848 81.92,10.798 81.76,10.76C81.612,10.731 81.461,10.714 81.31,10.71C80.44,10.71 80,11.26 80,12.37C79.974,12.797 80.087,13.221 80.32,13.58C80.56,13.881 80.937,14.04 81.32,14C81.698,13.998 82.072,13.92 82.42,13.77L82.42,14.35C82.061,14.504 81.669,14.566 81.28,14.53Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M86.31,14.45L86.31,11.68C86.333,11.399 86.247,11.12 86.07,10.9C85.869,10.716 85.602,10.622 85.33,10.64C84.958,10.608 84.591,10.744 84.33,11.01C84.093,11.363 83.983,11.786 84.02,12.21L84.02,14.45L83.37,14.45L83.37,8.37L84,8.37L84,10.21C84.013,10.393 84.013,10.577 84,10.76C84.135,10.556 84.321,10.39 84.54,10.28C84.792,10.157 85.07,10.096 85.35,10.1C85.776,10.068 86.199,10.2 86.53,10.47C86.846,10.783 87.017,11.215 87,11.66L87,14.45L86.31,14.45Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M93,14.45L92.87,13.84C92.704,14.073 92.485,14.261 92.23,14.39C91.979,14.49 91.71,14.537 91.44,14.53C91.077,14.552 90.719,14.434 90.44,14.2C90.191,13.957 90.059,13.617 90.08,13.27C90.08,12.4 90.77,11.95 92.15,11.91L92.88,11.91L92.88,11.64C92.909,11.374 92.829,11.107 92.66,10.9C92.476,10.723 92.224,10.635 91.97,10.66C91.548,10.678 91.135,10.787 90.76,10.98L90.56,10.49C90.776,10.368 91.008,10.277 91.25,10.22C91.498,10.152 91.753,10.119 92.01,10.12C92.416,10.084 92.821,10.206 93.14,10.46C93.413,10.754 93.547,11.151 93.51,11.55L93.51,14.47L93,14.45ZM91.54,14C91.889,14.016 92.23,13.894 92.49,13.66C92.73,13.412 92.853,13.074 92.83,12.73L92.83,12.35L92.19,12.35C91.803,12.339 91.419,12.422 91.07,12.59C90.844,12.735 90.713,12.992 90.73,13.26C90.716,13.459 90.793,13.654 90.94,13.79C91.108,13.931 91.321,14.005 91.54,14Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M97.58,13.28C97.596,13.646 97.426,13.996 97.13,14.21C96.757,14.444 96.32,14.556 95.88,14.53C95.424,14.554 94.97,14.461 94.56,14.26L94.56,13.66C94.974,13.876 95.433,13.993 95.9,14C96.171,14.015 96.44,13.956 96.68,13.83C96.858,13.732 96.966,13.543 96.96,13.34C96.957,13.171 96.876,13.012 96.74,12.91C96.477,12.731 96.191,12.59 95.89,12.49C95.581,12.391 95.283,12.26 95,12.1C94.851,12.006 94.724,11.879 94.63,11.73C94.542,11.575 94.497,11.399 94.5,11.22C94.516,10.88 94.705,10.57 95,10.4C95.346,10.173 95.757,10.064 96.17,10.09C96.634,10.094 97.093,10.189 97.52,10.37L97.29,10.9C96.921,10.736 96.524,10.647 96.12,10.64C95.881,10.621 95.642,10.669 95.43,10.78C95.282,10.858 95.189,11.013 95.19,11.18C95.188,11.284 95.219,11.386 95.28,11.47C95.355,11.566 95.451,11.645 95.56,11.7C95.802,11.825 96.052,11.932 96.31,12.02C96.68,12.133 97.021,12.324 97.31,12.58C97.487,12.769 97.584,13.021 97.58,13.28Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M71,28.45L69.23,28.45L67.53,22.45C67.46,22.19 67.37,21.82 67.26,21.33C67.15,20.84 67.08,20.5 67.06,20.33C67.06,20.63 66.94,21 66.84,21.47C66.74,21.94 66.65,22.28 66.58,22.47L64.93,28.4L63.15,28.4L61.86,23.4L60.54,18.4L62.21,18.4L63.64,24.22C63.86,25.16 64.02,25.98 64.12,26.7C64.12,26.31 64.25,25.88 64.35,25.4C64.45,24.92 64.54,24.53 64.62,24.24L66.25,18.4L67.87,18.4L69.53,24.26C69.733,25.084 69.89,25.919 70,26.76C70.105,25.92 70.269,25.088 70.49,24.27L72,18.46L73.66,18.46L71,28.45Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M78.15,28.59C77.134,28.657 76.135,28.294 75.4,27.59C74.701,26.819 74.34,25.799 74.4,24.76C74.341,23.707 74.668,22.669 75.32,21.84C75.965,21.125 76.898,20.735 77.86,20.78C78.74,20.735 79.598,21.066 80.22,21.69C80.83,22.378 81.143,23.282 81.09,24.2L81.09,25L76.09,25C76.077,25.621 76.291,26.225 76.69,26.7C77.11,27.111 77.684,27.325 78.27,27.29C78.69,27.294 79.11,27.251 79.52,27.16C79.947,27.065 80.363,26.924 80.76,26.74L80.76,28.05C80.382,28.231 79.982,28.362 79.57,28.44C79.103,28.538 78.627,28.588 78.15,28.59ZM77.86,22C77.399,21.978 76.95,22.157 76.63,22.49C76.296,22.886 76.102,23.382 76.08,23.9L79.51,23.9C79.537,23.388 79.377,22.883 79.06,22.48C78.75,22.152 78.311,21.976 77.86,22Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M86.78,20.75C87.632,20.705 88.454,21.079 88.98,21.75C89.557,22.595 89.835,23.609 89.77,24.63C89.835,25.656 89.553,26.674 88.97,27.52C88.417,28.176 87.602,28.555 86.745,28.555C85.888,28.555 85.073,28.176 84.52,27.52L84.42,27.52L84.12,28.41L82.92,28.41L82.92,17.82L84.52,17.82L84.52,21.88L84.58,21.88C85.073,21.154 85.903,20.728 86.78,20.75ZM86.36,22.07C85.829,22.023 85.307,22.235 84.96,22.64C84.627,23.219 84.474,23.884 84.52,24.55L84.52,24.66C84.467,25.355 84.62,26.051 84.96,26.66C85.301,27.094 85.84,27.327 86.39,27.28C86.913,27.301 87.409,27.042 87.69,26.6C88.026,25.99 88.179,25.295 88.13,24.6C88.13,22.93 87.54,22.07 86.36,22.07Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M101.65,28.45L100.65,25.68L96.83,25.68L95.83,28.45L94.13,28.45L97.87,18.45L99.65,18.45L103.38,28.45L101.65,28.45ZM100.22,24.27L99.28,21.55C99.21,21.37 99.12,21.08 99,20.69C98.88,20.3 98.8,20.01 98.75,19.83C98.612,20.452 98.431,21.063 98.21,21.66L97.31,24.27L100.22,24.27Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M108.37,28.59C107.509,28.641 106.675,28.267 106.14,27.59L106,27.59C106.07,28.22 106.1,28.59 106.1,28.75L106.1,31.85L104.49,31.85L104.49,20.89L105.79,20.89C105.79,21.03 105.9,21.37 106.02,21.89L106.1,21.89C106.592,21.131 107.456,20.691 108.36,20.74C109.211,20.698 110.032,21.071 110.56,21.74C111.137,22.585 111.415,23.599 111.35,24.62C111.409,25.645 111.128,26.661 110.55,27.51C110.04,28.199 109.227,28.601 108.37,28.59ZM108,22.07C107.471,22.022 106.95,22.23 106.6,22.63C106.264,23.163 106.11,23.792 106.16,24.42L106.16,24.66C106.107,25.355 106.26,26.051 106.6,26.66C106.939,27.097 107.479,27.331 108.03,27.28C108.549,27.298 109.04,27.034 109.31,26.59C109.645,25.997 109.802,25.32 109.76,24.64C109.802,23.97 109.646,23.302 109.31,22.72C109.019,22.288 108.52,22.041 108,22.07Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M117.09,28.59C116.229,28.641 115.395,28.267 114.86,27.59L114.77,27.59C114.83,28.22 114.86,28.59 114.86,28.75L114.86,31.85L113.26,31.85L113.26,20.89L114.55,20.89C114.55,21.03 114.67,21.37 114.78,21.89L114.86,21.89C115.354,21.132 116.217,20.693 117.12,20.74C117.972,20.695 118.794,21.069 119.32,21.74C119.897,22.585 120.175,23.599 120.11,24.62C120.169,25.645 119.888,26.661 119.31,27.51C118.791,28.21 117.961,28.614 117.09,28.59ZM116.7,22.07C116.171,22.022 115.65,22.23 115.3,22.63C114.964,23.163 114.81,23.792 114.86,24.42L114.86,24.66C114.807,25.355 114.96,26.051 115.3,26.66C115.641,27.094 116.18,27.327 116.73,27.28C117.249,27.298 117.74,27.034 118.01,26.59C118.345,25.997 118.502,25.32 118.46,24.64C118.505,23.971 118.352,23.303 118.02,22.72C117.723,22.29 117.222,22.043 116.7,22.07Z" style="fill:white;fill-rule:nonzero;"/>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

31
.github/assets/badge-windows-store.svg vendored Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 864 312" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g id="Layer_2">
<rect x="2.3" y="2.3" width="859.5" height="307.5"/>
<path d="M4.5,4.5L859.5,4.5L859.5,307.5L4.5,307.5L4.5,4.5ZM0,312L864,312L864,0L0,0L0,312Z" style="fill:rgb(210,210,210);fill-rule:nonzero;"/>
</g>
<g id="Layer_1">
<rect x="70.5" y="68.6" width="83.8" height="83.8" style="fill:rgb(242,80,34);"/>
<rect x="163" y="68.6" width="83.8" height="83.8" style="fill:rgb(127,186,0);"/>
<rect x="70.5" y="161" width="83.8" height="83.8" style="fill:rgb(0,164,239);"/>
<rect x="163" y="161" width="83.8" height="83.8" style="fill:rgb(255,185,0);"/>
<path d="M408.3,163C408.3,160.5 409.2,158.5 411,156.8C412.8,155.1 414.9,154.3 417.4,154.3C420,154.3 422.2,155.2 423.9,156.9C425.6,158.6 426.5,160.7 426.5,163C426.5,165.4 425.6,167.5 423.8,169.1C422,170.8 419.9,171.6 417.3,171.6C414.7,171.6 412.6,170.8 410.8,169.1C409.2,167.4 408.3,165.4 408.3,163M424.8,244.8L409.9,244.8L409.9,181.3L424.8,181.3L424.8,244.8Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M470.2,233.9C472.4,233.9 474.9,233.4 477.6,232.4C480.3,231.4 482.7,230 485,228.3L485,242.2C482.6,243.6 479.9,244.6 476.9,245.3C473.9,246 470.5,246.4 466.9,246.4C457.6,246.4 450,243.4 444.1,237.5C438.2,231.6 435.3,224 435.3,214.9C435.3,204.7 438.3,196.3 444.3,189.7C450.3,183.1 458.7,179.8 469.7,179.8C472.5,179.8 475.3,180.2 478.2,180.9C481.1,181.6 483.3,182.5 485,183.4L485,197.7C482.7,196 480.3,194.7 477.9,193.8C475.5,192.9 473,192.4 470.5,192.4C464.6,192.4 459.9,194.3 456.2,198.1C452.6,201.9 450.8,207.1 450.8,213.6C450.8,220 452.5,225 456,228.6C459.5,232.2 464.2,233.9 470.2,233.9" style="fill:white;fill-rule:nonzero;"/>
<path d="M527.5,180.3C528.7,180.3 529.8,180.4 530.7,180.5C531.6,180.7 532.5,180.9 533.1,181.1L533.1,196.2C532.3,195.6 531.2,195.1 529.7,194.6C528.2,194.1 526.4,193.8 524.2,193.8C520.5,193.8 517.4,195.3 514.9,198.4C512.4,201.5 511.1,206.2 511.1,212.7L511.1,244.8L496.2,244.8L496.2,181.3L511.1,181.3L511.1,191.3L511.3,191.3C512.7,187.8 514.7,185.1 517.5,183.2C520.3,181.3 523.6,180.3 527.5,180.3" style="fill:white;fill-rule:nonzero;"/>
<path d="M533.9,214C533.9,203.5 536.9,195.2 542.8,189C548.7,182.9 557,179.8 567.5,179.8C577.4,179.8 585.2,182.8 590.8,188.7C596.4,194.6 599.2,202.6 599.2,212.6C599.2,222.9 596.2,231.1 590.3,237.2C584.4,243.3 576.3,246.3 566.1,246.3C556.3,246.3 548.4,243.4 542.7,237.6C536.8,231.9 533.9,224 533.9,214M549.5,213.5C549.5,220.1 551,225.2 554,228.7C557,232.2 561.3,233.9 566.9,233.9C572.3,233.9 576.5,232.2 579.3,228.7C582.1,225.2 583.6,220 583.6,213.1C583.6,206.3 582.1,201.1 579.2,197.6C576.3,194.1 572.1,192.4 566.8,192.4C561.3,192.4 557.1,194.2 554,197.9C551,201.6 549.5,206.7 549.5,213.5" style="fill:white;fill-rule:nonzero;"/>
<path d="M621.4,198C621.4,200.1 622.1,201.8 623.4,203C624.8,204.2 627.8,205.7 632.4,207.6C638.4,210 642.6,212.7 645,215.7C647.4,218.7 648.6,222.3 648.6,226.5C648.6,232.5 646.3,237.3 641.7,240.9C637.1,244.5 630.9,246.3 623.1,246.3C620.5,246.3 617.6,246 614.4,245.3C611.2,244.7 608.5,243.8 606.3,242.9L606.3,228.2C609,230.1 611.9,231.6 615.1,232.7C618.2,233.8 621.1,234.4 623.6,234.4C627,234.4 629.5,233.9 631.1,233C632.7,232.1 633.5,230.5 633.5,228.2C633.5,226.1 632.7,224.4 631,223C629.3,221.6 626.2,219.9 621.5,218.1C616,215.8 612.1,213.2 609.8,210.3C607.5,207.4 606.3,203.7 606.3,199.3C606.3,193.6 608.6,188.9 613.1,185.2C617.6,181.5 623.5,179.7 630.8,179.7C633,179.7 635.5,179.9 638.3,180.4C641.1,180.9 643.4,181.5 645.2,182.3L645.2,196.5C643.2,195.2 640.9,194.1 638.3,193.1C635.7,192.2 633,191.7 630.5,191.7C627.7,191.7 625.4,192.3 623.9,193.4C622.2,194.5 621.4,196.1 621.4,198" style="fill:white;fill-rule:nonzero;"/>
<path d="M655.2,214C655.2,203.5 658.2,195.2 664.1,189C670,182.9 678.3,179.8 688.8,179.8C698.7,179.8 706.5,182.8 712.1,188.7C717.7,194.6 720.5,202.6 720.5,212.6C720.5,222.9 717.5,231.1 711.6,237.2C705.7,243.3 697.6,246.3 687.4,246.3C677.6,246.3 669.7,243.4 664,237.6C658.1,231.9 655.2,224 655.2,214M670.7,213.5C670.7,220.1 672.2,225.2 675.2,228.7C678.2,232.2 682.5,233.9 688.1,233.9C693.5,233.9 697.7,232.2 700.5,228.7C703.3,225.2 704.8,220 704.8,213.1C704.8,206.3 703.3,201.1 700.4,197.6C697.5,194.1 693.3,192.4 688,192.4C682.5,192.4 678.3,194.2 675.2,197.9C672.2,201.6 670.7,206.7 670.7,213.5" style="fill:white;fill-rule:nonzero;"/>
<path d="M769.8,193.6L769.8,226.2C769.8,233 771.4,238 774.5,241.4C777.6,244.8 782.4,246.4 788.7,246.4C790.8,246.4 793,246.2 795.2,245.7C797.4,245.2 799,244.8 799.9,244.2L799.9,231.8C799,232.4 797.9,232.9 796.7,233.3C795.5,233.7 794.4,233.9 793.6,233.9C790.6,233.9 788.3,233.1 786.9,231.5C785.5,229.9 784.8,227.1 784.8,223.2L784.8,193.5L800,193.5L800,181.3L784.9,181.3L784.9,162.5L769.9,167.1L769.9,181.4L747.6,181.4L747.6,173.7C747.6,169.9 748.4,167 750.1,165C751.8,163 754.2,162.1 757.3,162.1C758.9,162.1 760.3,162.3 761.6,162.7C762.8,163.1 763.7,163.5 764.2,163.8L764.2,150.9C763.1,150.5 761.9,150.3 760.5,150.1C759.1,149.9 757.5,149.8 755.7,149.8C748.9,149.8 743.3,151.9 739,156.2C734.7,160.5 732.5,165.9 732.5,172.6L732.5,181.4L721.9,181.4L721.9,193.6L732.5,193.6L732.5,244.9L747.6,244.9L747.6,193.6L769.8,193.6Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M395.5,156.2L395.5,244.8L380.1,244.8L380.1,175.4L379.9,175.4L352.4,244.8L342.2,244.8L314,175.4L313.8,175.4L313.8,244.8L299.6,244.8L299.6,156.2L321.6,156.2L347.1,221.9L347.5,221.9L374.4,156.2L395.5,156.2Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M340,117.9C334.7,120.9 328.7,122.4 322,122.4C316.9,122.4 312.4,121.3 308.4,119C304.5,116.8 301.4,113.6 299.3,109.5C297.2,105.4 296.1,100.8 296.1,95.7C296.1,90.3 297.3,85.4 299.6,81.2C301.9,77 305.2,73.6 309.5,71.2C313.8,68.8 318.6,67.6 324,67.6C326.7,67.6 329.4,67.9 332.1,68.4C334.8,68.9 337,69.6 338.7,70.4L338.7,78.4C334.7,75.7 329.6,74.4 323.4,74.4C319.7,74.4 316.4,75.3 313.4,77.1C310.4,78.9 308.1,81.4 306.5,84.5C304.9,87.7 304.1,91.3 304.1,95.3C304.1,101.6 305.8,106.6 309.1,110.3C312.4,114 317,115.8 322.8,115.8C326.5,115.8 329.8,115.1 332.6,113.6L332.6,99.9L321.3,99.9L321.3,93.3L340,93.3L340,117.9Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M383.1,104.6L356.9,104.6C357,108.4 358.2,111.3 360.2,113.4C362.3,115.4 365,116.5 368.4,116.5C372.9,116.5 376.8,115.2 380.2,112.6L380.2,119C378.7,120 376.8,120.9 374.5,121.5C372.2,122.1 369.8,122.4 367.4,122.4C361.7,122.4 357.2,120.7 354.1,117.3C351,113.9 349.4,109.1 349.4,102.9C349.4,99.1 350.2,95.6 351.7,92.6C353.2,89.5 355.4,87.1 358.1,85.4C360.8,83.7 363.9,82.8 367.2,82.8C372.1,82.8 376,84.4 378.8,87.6C381.6,90.8 383,95.2 383,100.9L383,104.6L383.1,104.6ZM375.8,98.9C375.8,95.6 375,93.1 373.5,91.4C372,89.7 369.9,88.8 367.1,88.8C364.6,88.8 362.4,89.7 360.5,91.5C358.6,93.3 357.5,95.8 356.9,98.9L375.8,98.9Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M411.5,121.1C410.8,121.5 409.9,121.8 408.6,122C407.4,122.2 406.3,122.3 405.3,122.3C398.3,122.3 394.8,118.4 394.8,110.7L394.8,89.7L388.4,89.7L388.4,83.7L394.8,83.7L394.8,74.7L402.1,72.4L402.1,83.6L411.4,83.6L411.4,89.6L402.1,89.6L402.1,109.4C402.1,111.9 402.5,113.7 403.3,114.7C404.1,115.7 405.5,116.2 407.6,116.2C409,116.2 410.3,115.8 411.4,115L411.4,121.1L411.5,121.1Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M447.7,70.3C447.7,71.5 447.3,72.5 446.4,73.4C445.5,74.3 444.4,74.7 443.1,74.7C441.8,74.7 440.7,74.3 439.8,73.4C438.9,72.6 438.5,71.5 438.5,70.2C438.5,68.9 439,67.8 439.9,67C440.8,66.2 441.9,65.7 443.1,65.7C444.3,65.7 445.4,66.1 446.3,67C447.3,68 447.7,69 447.7,70.3M446.7,121.5L439.4,121.5L439.4,83.7L446.7,83.7L446.7,121.5Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M478.4,121.1C477.7,121.5 476.8,121.8 475.5,122C474.3,122.2 473.2,122.3 472.2,122.3C465.2,122.3 461.7,118.4 461.7,110.7L461.7,89.7L455.3,89.7L455.3,83.7L461.7,83.7L461.7,74.7L469,72.4L469,83.6L478.3,83.6L478.3,89.6L469,89.6L469,109.4C469,111.9 469.4,113.7 470.2,114.7C471,115.7 472.4,116.2 474.5,116.2C475.9,116.2 477.2,115.8 478.3,115L478.3,121.1L478.4,121.1Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M526.2,71.7C525,71.1 523.7,70.7 522.2,70.7C518.1,70.7 516.1,73.2 516.1,78.2L516.1,83.6L524.7,83.6L524.7,89.6L516.1,89.6L516.1,121.4L508.8,121.4L508.8,89.7L502.4,89.7L502.4,83.7L508.8,83.7L508.8,77.9C508.8,73.9 509.9,70.7 512.2,68.3C514.5,65.9 517.6,64.7 521.6,64.7C523.6,64.7 525.1,64.9 526.3,65.4L526.3,71.7L526.2,71.7Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M553.1,91C552.7,90.7 551.9,90.4 550.9,90.1C549.9,89.9 549,89.7 548.3,89.7C545.7,89.7 543.6,90.9 542,93.2C540.4,95.5 539.6,98.5 539.6,102.2L539.6,121.5L532.3,121.5L532.3,83.7L539.6,83.7L539.6,91.3L539.8,91.3C540.6,88.7 541.9,86.7 543.6,85.2C545.3,83.7 547.3,83 549.5,83C551,83 552.2,83.2 553,83.5L553,91L553.1,91Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M594.8,102.4C594.8,108.5 593,113.4 589.5,117C586,120.6 581.3,122.4 575.5,122.4C569.8,122.4 565.2,120.6 561.8,117.1C558.4,113.6 556.7,108.9 556.7,103C556.7,96.7 558.5,91.8 562,88.2C565.5,84.6 570.3,82.8 576.4,82.8C582.1,82.8 586.6,84.5 589.8,88C593.2,91.5 594.8,96.3 594.8,102.4M587.3,102.6C587.3,98.1 586.3,94.7 584.4,92.4C582.4,90.1 579.7,88.9 576.1,88.9C572.5,88.9 569.6,90.1 567.5,92.6C565.4,95 564.4,98.5 564.4,102.9C564.4,107.2 565.4,110.5 567.5,112.9C569.6,115.3 572.4,116.5 576.1,116.5C579.8,116.5 582.6,115.3 584.5,113C586.3,110.5 587.3,107.1 587.3,102.6" style="fill:white;fill-rule:nonzero;"/>
<path d="M660.1,121.5L652.8,121.5L652.8,100C652.8,96.1 652.2,93.3 651,91.5C649.8,89.7 647.7,88.9 644.8,88.9C642.4,88.9 640.3,90 638.7,92.2C637,94.4 636.2,97.1 636.2,100.1L636.2,121.5L628.9,121.5L628.9,99.3C628.9,92.4 626.2,88.9 620.9,88.9C618.4,88.9 616.3,90 614.7,92.1C613.1,94.2 612.3,96.9 612.3,100.2L612.3,121.6L605,121.6L605,83.7L612.3,83.7L612.3,89.6L612.4,89.6C615.1,85 619.1,82.8 624.2,82.8C626.6,82.8 628.8,83.5 630.8,84.8C632.7,86.1 634.1,88 635,90.4C636.5,87.8 638.2,85.9 640.3,84.6C642.4,83.4 644.8,82.7 647.6,82.7C655.9,82.7 660,87.8 660,98.1L660,121.5L660.1,121.5Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

45
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
assignees:
- "ricoberger"
groups:
github-actions:
patterns:
- "*"
- package-ecosystem: "pub"
directory: "/app"
schedule:
interval: "monthly"
assignees:
- "ricoberger"
groups:
pub:
patterns:
- "*"
- package-ecosystem: "docker"
directory: "/supabase/functions/_cmd"
schedule:
interval: "monthly"
assignees:
- "ricoberger"
groups:
docker:
patterns:
- "*"
- package-ecosystem: "npm"
directory: "/landing"
schedule:
interval: "monthly"
assignees:
- "ricoberger"
groups:
npm:
patterns:
- "*"

View File

@@ -22,7 +22,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -36,13 +36,13 @@ jobs:
fi
- name: Setup QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
@@ -50,7 +50,7 @@ jobs:
- name: Build and Push Docker Image
id: docker_build
uses: docker/build-push-action@v4
uses: docker/build-push-action@v6
with:
push: true
context: ./supabase/functions
@@ -69,7 +69,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -87,11 +87,14 @@ jobs:
supabase db push
supabase functions deploy add-source-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy add-or-update-source-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
# supabase functions deploy add-source-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy delete-user-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy generate-magic-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy image-proxy-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy profile-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
# supabase functions deploy profile-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy profile-v2 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy revenuecat-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy stripe-create-billing-portal-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy stripe-create-checkout-session-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy stripe-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
@@ -107,21 +110,26 @@ jobs:
supabase db push
supabase functions deploy add-or-update-source-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy add-source-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy delete-user-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy generate-magic-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy image-proxy-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy profile-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy profile-v2 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy revenuecat-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy stripe-create-billing-portal-link-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy stripe-create-checkout-session-v1 --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
supabase functions deploy stripe-webhooks-v1 --no-verify-jwt --project-ref $PROJECT_ID --import-map supabase/functions/import_map.json
# The "Web" job builds the Flutter web app and publishes it to Cloudflare Pages. The job only runs when a commit is
# pushed to the main branch or a new tag is created.
# The "Web" job builds the Flutter web app and publishes it to Cloudflare Pages. The job only runs on pull requests or
# when a commit is pushed to the main branch or a new tag is created.
#
# When the job runs on a pull request it only builds the app but doesn't upload the build to Cloudflare.
web:
name: Web
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || (github.event_name == 'release' && github.event.action == 'published')
if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main' || (github.event_name == 'release' && github.event.action == 'published')
permissions:
contents: read
defaults:
@@ -130,7 +138,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -162,7 +170,7 @@ jobs:
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.7.12'
flutter-version: '3.22.2'
channel: 'stable'
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
@@ -179,6 +187,7 @@ jobs:
- name: Publish to Cloudflare Pages
uses: cloudflare/pages-action@v1
if: github.ref == 'refs/heads/main' || (github.event_name == 'release' && github.event.action == 'published')
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
@@ -190,7 +199,7 @@ jobs:
# runs for pull requests and when a new release is published.
macos:
name: macOS
runs-on: macos-latest
runs-on: macos-14
if: github.event_name == 'pull_request' || (github.event_name == 'release' && github.event.action == 'published')
permissions:
contents: write
@@ -200,12 +209,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.7.12'
flutter-version: '3.22.2'
channel: 'stable'
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
@@ -218,7 +227,7 @@ jobs:
- name: Build
run: |
flutter config --enable-macos-desktop
flutter build macos --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }}
FLUTTER_XCODE_CODE_SIGN_IDENTITY="" FLUTTER_XCODE_CODE_SIGNING_REQUIRED=NO flutter build macos --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }}
- name: Package
run: |
@@ -226,7 +235,7 @@ jobs:
- name: Upload Artifacts (PR)
if: ${{ github.event_name == 'pull_request' }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: feeddeck-macos-universal.zip
path: app/build/macos/Build/Products/Release/feeddeck-macos-universal.zip
@@ -239,10 +248,10 @@ jobs:
upload_url: ${{ github.event.release.upload_url }}
asset_path: app/build/macos/Build/Products/Release/feeddeck-macos-universal.zip
# The "Linux" job builds the Flutter Linux app and uploads it to the GitHub release or the pull request. The job only
# runs for pull requests and when a new release is published.
linux:
name: Linux
# The "Linux (x86_64)" job builds the Flutter Linux app and uploads it to the GitHub release or the pull request. The
# job only runs for pull requests and when a new release is published.
linux-x86_64:
name: Linux (x86_64)
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || (github.event_name == 'release' && github.event.action == 'published')
permissions:
@@ -253,18 +262,21 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install Packages
run: |
# Required for Flutter
sudo apt-get update -y
sudo apt-get install -y ninja-build libgtk-3-dev
# Required for Package "media_kit" which is used via "just_audio_media_kit" for Linux and Windows:
# See: https://pub.dev/packages/media_kit and https://pub.dev/packages/just_audio_media_kit
sudo apt-get install -y libmpv-dev mpv
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.7.12'
flutter-version: '3.22.2'
channel: 'stable'
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
@@ -281,13 +293,16 @@ jobs:
- name: Package
run: |
cp linux/flatpak/app.feeddeck.feeddeck.desktop build/linux/x64/release/bundle/
cp linux/flatpak/app.feeddeck.feeddeck.metainfo.xml build/linux/x64/release/bundle/
cp linux/flatpak/app.feeddeck.feeddeck.svg build/linux/x64/release/bundle/
cd build
cp -r linux/x64/release/bundle/ feeddeck-linux-x86_64
tar -czf feeddeck-linux-x86_64.tar.gz feeddeck-linux-x86_64
- name: Upload Artifacts (PR)
if: ${{ github.event_name == 'pull_request' }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: feeddeck-linux-x86_64.tar.gz
path: app/build/feeddeck-linux-x86_64.tar.gz
@@ -300,11 +315,82 @@ jobs:
upload_url: ${{ github.event.release.upload_url }}
asset_path: app/build/feeddeck-linux-x86_64.tar.gz
# The "Linux (arm64)" job builds the Flutter Linux app and uploads it to the GitHub release or the pull request. The
# job only runs for pull requests and when a new release is published.
#
# NOTE: Normally this job should run for every pull request and when a new release is published, but since we have to
# pay for the "ubicloud-standard-2-arm" runner, we only run the job when a new release is published.
linux-arm64:
name: Linux (arm64)
runs-on: ubicloud-standard-2-arm
if: github.event_name == 'release' && github.event.action == 'published'
# if: github.event_name == 'pull_request' || (github.event_name == 'release' && github.event.action == 'published')
permissions:
contents: write
defaults:
run:
working-directory: "app"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Packages
run: |
# Required for Flutter
sudo apt-get update -y
sudo apt-get install -y ninja-build libgtk-3-dev
# Required for Package "media_kit" which is used via "just_audio_media_kit" for Linux and Windows:
# See: https://pub.dev/packages/media_kit and https://pub.dev/packages/just_audio_media_kit
sudo apt-get install -y libmpv-dev mpv
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.22.2'
channel: 'master'
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:'
- name: Install Dependencies
run: |
flutter pub get
- name: Build
run: |
flutter config --enable-linux-desktop
flutter build linux --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }}
- name: Package
run: |
cp linux/flatpak/app.feeddeck.feeddeck.desktop build/linux/arm64/release/bundle/
cp linux/flatpak/app.feeddeck.feeddeck.metainfo.xml build/linux/arm64/release/bundle/
cp linux/flatpak/app.feeddeck.feeddeck.svg build/linux/arm64/release/bundle/
cd build
cp -r linux/arm64/release/bundle/ feeddeck-linux-arm64
tar -czf feeddeck-linux-arm64.tar.gz feeddeck-linux-arm64
- name: Upload Artifacts (PR)
if: ${{ github.event_name == 'pull_request' }}
uses: actions/upload-artifact@v4
with:
name: feeddeck-linux-arm64.tar.gz
path: app/build/feeddeck-linux-arm64.tar.gz
if-no-files-found: error
- name: Upload Artifacts (Release)
uses: shogo82148/actions-upload-release-asset@v1
if: ${{ github.event_name == 'release' && github.event.action == 'published' }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: app/build/feeddeck-linux-arm64.tar.gz
# The "Windows" job builds the Flutter Windows app and uploads it to the GitHub release or the pull request. The job
# only runs for pull requests and when a new release is published.
windows:
name: Windows
runs-on: windows-latest
runs-on: windows-2019
if: github.event_name == 'pull_request' || (github.event_name == 'release' && github.event.action == 'published')
permissions:
contents: write
@@ -314,12 +400,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.7.12'
flutter-version: '3.22.2'
channel: 'stable'
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
@@ -333,19 +419,22 @@ jobs:
run: |
flutter config --enable-windows-desktop
flutter build windows --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }}
- name: Create Archive
run: |
Compress-Archive -Path build/windows/x64/runner/Release/* -Destination feeddeck-windows-x86_64.zip
- name: Package
run: |
flutter pub run msix:create --output-path build --output-name feeddeck
cd build
7z a -tzip feeddeck-windows-x86_64.zip feeddeck.msix
7z a -tzip feeddeck-windows-x86_64-msix.zip feeddeck.msix
- name: Upload Artifacts (PR)
if: ${{ github.event_name == 'pull_request' }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: feeddeck-windows-x86_64.zip
path: app/build/feeddeck-windows-x86_64.zip
path: app/feeddeck-windows-x86_64.zip
if-no-files-found: error
- name: Upload Artifacts (Release)
@@ -353,4 +442,86 @@ jobs:
if: ${{ github.event_name == 'release' && github.event.action == 'published' }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: app/build/feeddeck-windows-x86_64.zip
asset_path: app/feeddeck-windows-x86_64.zip
- name: Upload Artifacts (PR)
if: ${{ github.event_name == 'pull_request' }}
uses: actions/upload-artifact@v4
with:
name: feeddeck-windows-x86_64-msix.zip
path: app/build/feeddeck-windows-x86_64-msix.zip
if-no-files-found: error
- name: Upload Artifacts (Release)
uses: shogo82148/actions-upload-release-asset@v1
if: ${{ github.event_name == 'release' && github.event.action == 'published' }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: app/build/feeddeck-windows-x86_64-msix.zip
# The "iOS" job builds the Flutter iOS app on every pull request. This is only used to test that the build of the iOS
# app works. The artifact of the build isn't uploaded / used.
ios:
name: iOS
runs-on: macos-14
if: github.event_name == 'pull_request' || (github.event_name == 'release' && github.event.action == 'published')
defaults:
run:
working-directory: "app"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.22.2'
channel: 'stable'
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:'
- name: Install Dependencies
run: |
flutter pub get
- name: Build
run: |
flutter config --enable-ios
flutter build ipa --no-codesign --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }}
# The "Android" job builds the Flutter Android app on every pull request. This is only used to test that the build of
# the Android app works. The artifact of the build isn't uploaded / used.
android:
name: Android
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' || (github.event_name == 'release' && github.event.action == 'published')
defaults:
run:
working-directory: "app"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
run: echo "JAVA_HOME=$JAVA_HOME_17_X64" >> $GITHUB_ENV
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.22.2'
channel: 'stable'
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:'
- name: Install Dependencies
run: |
flutter pub get
- name: Build
run: |
flutter config --enable-android
flutter build appbundle --release --dart-define SUPABASE_URL=${{ secrets.SUPABASE_PROD_URL }} --dart-define SUPABASE_ANON_KEY=${{ secrets.SUPABASE_PROD_ANON_KEY }} --dart-define SUPABASE_SITE_URL=${{ secrets.SUPABASE_PROD_SITE_URL }} --dart-define GOOGLE_CLIENT_ID=${{ secrets.SUPABASE_PROD_GOOGLE_CLIENT_ID }}

View File

@@ -0,0 +1,53 @@
name: Continuous Integration
on:
push:
branches:
- main
pull_request:
jobs:
flutter:
name: Flutter
runs-on: ubuntu-latest
defaults:
run:
working-directory: "app"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.22.2'
channel: 'stable'
cache: true
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:'
- name: Install Dependencies
run: |
flutter pub get
- name: Test
run: |
flutter test
deno:
name: Deno
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: Test
run: |
deno test --allow-env --import-map=supabase/functions/import_map.json supabase/functions

View File

@@ -16,7 +16,7 @@ jobs:
steps:
- name: Update Changelog
uses: release-drafter/release-drafter@v5
uses: release-drafter/release-drafter@v6
with:
config-name: release.yaml
disable-autolabeler: true
@@ -37,17 +37,17 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: "16"
node-version: "20"
cache: npm
cache-dependency-path: landing/package-lock.json
- name: Setup Pages
uses: actions/configure-pages@v3
uses: actions/configure-pages@v5
- name: Install Dependencies
run: |
@@ -58,7 +58,7 @@ jobs:
npm run build
- name: Upload Artifact
uses: actions/upload-pages-artifact@v2
uses: actions/upload-pages-artifact@v3
with:
path: ./landing/out
@@ -78,4 +78,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
uses: actions/deploy-pages@v4

7
.gitignore vendored
View File

@@ -1,8 +1,11 @@
# Visual Studio Code Launch Configurations
.vscode/launch.json
# Visual Studio Code
.vscode
# Environment Variables
/supabase/.env.local
/supabase/.env.dev
/supabase/.env.stage
/supabase/.env.prod
# Deno
/coverage_deno

17
.vscode/settings.json vendored
View File

@@ -1,17 +0,0 @@
{
"deno.enable": true,
"deno.unstable": true,
"deno.lint": true,
"deno.enablePaths": [
"./supabase/functions"
],
"deno.importMap": "./supabase/functions/import_map.json",
"editor.formatOnSave": true,
"editor.defaultFormatter": "denoland.vscode-deno",
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[html]": {
"editor.defaultFormatter": "vscode.html-language-features"
}
}

View File

@@ -57,116 +57,46 @@ check your installed version:
```sh
$ flutter --version
Flutter 3.7.12 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 4d9e56e694 (8 weeks ago) • 2023-04-17 21:47:46 -0400
Engine • revision 1a65d409c7
Tools • Dart 2.19.6 • DevTools 2.20.1
Flutter 3.22.2 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 761747bfc5 (3 days ago) • 2024-06-05 22:15:13 +0200
Engine • revision edd8546116
Tools • Dart 3.4.3 • DevTools 2.34.3
$ deno --version
deno 1.36.4 (release, aarch64-apple-darwin)
v8 11.6.189.12
typescript 5.1.6
deno 1.40.2 (release, aarch64-apple-darwin)
v8 12.1.285.6
typescript 5.3.3
```
### Working with Flutter
We are recommending to use the
[Visual Studio Code](https://docs.flutter.dev/development/tools/vs-code)
extensions for development.
To run the app you can use the [`run.sh`](./app/run.sh) script, which will
automatically load the `.env` file from the Supabase project and passes the
required variables to the `flutter run` command:
The easiest way to run the Flutter app within Visual Studio Code is to create a
`.vscode/launch.json` file. Within the different configurations you have to
provide the following arguments: `--dart-define SUPABASE_URL=<SUPABASE_URL>`,
`--dart-define SUPABASE_ANON_KEY=<SUPABASE_ANON_KEY>`,
`--dart-define SUPABASE_SITE_URL=<SUPABASE_SITE_URL>` and
`--dart-define GOOGLE_CLIENT_ID=<GOOGLE_CLIENT_ID>`.
<details>
<summary>Example: `.vscode/launch.json`</summary>
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "FeedDeck (Chrome)",
"request": "launch",
"type": "dart",
"args": [
"-d",
"chrome",
"--web-port",
"3000",
"--web-browser-flag=--disable-web-security",
"--dart-define",
"SUPABASE_URL=<SUPABASE_URL>",
"--dart-define",
"SUPABASE_ANON_KEY=<SUPABASE_ANON_KEY>",
"--dart-define",
"SUPABASE_SITE_URL=<SUPABASE_SITE_URL>",
"--dart-define",
"GOOGLE_CLIENT_ID=<GOOGLE_CLIENT_ID>"
]
},
{
"name": "FeedDeck (Web Server)",
"request": "launch",
"type": "dart",
"args": [
"-d",
"web-server",
"--web-port",
"3000",
"--dart-define",
"SUPABASE_URL=<SUPABASE_URL>",
"--dart-define",
"SUPABASE_ANON_KEY=<SUPABASE_ANON_KEY>",
"--dart-define",
"SUPABASE_SITE_URL=<SUPABASE_SITE_URL>",
"--dart-define",
"GOOGLE_CLIENT_ID=<GOOGLE_CLIENT_ID>"
]
},
{
"name": "FeedDeck (iOS)",
"request": "launch",
"type": "dart",
"args": [
"-d",
"iPhone 14 Pro Max",
"--dart-define",
"SUPABASE_URL=<SUPABASE_URL>",
"--dart-define",
"SUPABASE_ANON_KEY=<SUPABASE_ANON_KEY>",
"--dart-define",
"SUPABASE_SITE_URL=<SUPABASE_SITE_URL>",
"--dart-define",
"GOOGLE_CLIENT_ID=<GOOGLE_CLIENT_ID>"
]
},
{
"name": "FeedDeck (macOS)",
"request": "launch",
"type": "dart",
"args": [
"-d",
"macOS",
"--dart-define",
"SUPABASE_URL=<SUPABASE_URL>",
"--dart-define",
"SUPABASE_ANON_KEY=<SUPABASE_ANON_KEY>",
"--dart-define",
"SUPABASE_SITE_URL=<SUPABASE_SITE_URL>",
"--dart-define",
"GOOGLE_CLIENT_ID=<GOOGLE_CLIENT_ID>"
]
}
]
}
```sh
./run.sh --device="chrome" --environment="local"
```
</details>
To run the tests the following command can be used:
```sh
flutter test
```
To check the test coverage the `--coverage` flag can be added to the command and
an HTML report can be generated:
```sh
flutter test --coverage
# To generate the HTML report lcov is required, which can be installed via Homebrew:
brew install lcov
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html
```
#### Sort all Imports
@@ -300,6 +230,38 @@ cd supabase/functions/_cmd
docker-compose up --build
```
To build the Docker image, the following commands can be run:
```sh
docker build -f supabase/functions/_cmd/Dockerfile -t ghcr.io/feeddeck/feeddeck:dev supabase/functions
# To build the Docker image for another platform use the following:
docker buildx build --platform linux/amd64 -f supabase/functions/_cmd/Dockerfile -t ghcr.io/feeddeck/feeddeck:dev supabase/functions
# The Docker image can then be used to run the scheduler, worker or tools, e.g.
docker run ghcr.io/feeddeck/feeddeck:dev tools get-feed '{"type": "reddit", "options": {"reddit": "/r/kubernetes"}}'
```
To run the tests for our code, the following command can be used:
```sh
deno test --allow-env --import-map=supabase/functions/import_map.json supabase/functions
```
To check the test coverage the `--coverage` flag can be added to the command and
an HTML report can be generated:
```sh
deno test --allow-env --import-map=supabase/functions/import_map.json supabase/functions --coverage=coverage_deno
# To generate the HTML report lcov is required, which can be installed via Homebrew:
brew install lcov
deno coverage coverage_deno --lcov --output=coverage_deno/coverage_deno.lcov
genhtml -o coverage_deno/html coverage_deno/coverage_deno.lcov
open coverage_deno/html/index.html
```
## Hosting
FeedDeck uses Supabase as backend. For Supabase we can use
@@ -321,11 +283,14 @@ supabase secrets set --env-file supabase/.env
supabase secrets list
# Deploy all functions
supabase functions deploy add-or-update-source-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy add-source-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy delete-user-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy generate-magic-link-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy image-proxy-v1 --no-verify-jwt --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy profile-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy profile-v2 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy revenuecat-webhooks-v1 --no-verify-jwt --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy stripe-create-billing-portal-link-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy stripe-create-checkout-session-v1 --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
supabase functions deploy stripe-webhooks-v1 --no-verify-jwt --project-ref <PROJECT-ID> --import-map supabase/functions/import_map.json
@@ -411,26 +376,32 @@ Android, macOS, Windows and Linux if you do not want to use the official ones.
2. Update the `version` key and the `msix_config.msix_version` key in the
`pubspec.yaml` file.
3. Delete the `build/` and `.dart_tool/` directories via the `flutter clean`
3. Add the new release to the `releases` section in
[`app.feeddeck.feeddeck.metainfo.xml`](app/linux/flatpak/app.feeddeck.feeddeck.metainfo.xml).
4. Delete the `build/` and `.dart_tool/` directories via the `flutter clean`
command.
4. Build the app for Web by running `flutter build web`. The build can be found
5. Build the app for Web by running `flutter build web`. The build can be found
at `app/build/web` and must be uploaded to your hosting provider.
5. Build the app for Linux by running `flutter build linux --release`.
6. Build the app for Linux by running `flutter build linux --release`. Update
the `app.feeddeck.feeddeck.yml` file at
[github.com/flathub/app.feeddeck.feeddeck](https://github.com/flathub/app.feeddeck.feeddeck)
with the new release.
6. Build the app for macOS by running `flutter build macos --release`. Open
7. Build the app for macOS by running `flutter build macos --release`. Open
Xcode and select **Product** > **Archive** to create and open the archive.
After that the **Validate App** and **Distribute App** options can be used to
upload the build to
[https://appstoreconnect.apple.com](https://appstoreconnect.apple.com).
7. Build the app for Windows by running `flutter build windows --release`. and
8. Build the app for Windows by running `flutter build windows --release`. and
`flutter pub run msix:create --output-path build --output-name feeddeck`. The
build can be found at `app/build/feeddeck.msix` and must be uploaded to
[https://partner.microsoft.com/en-us/dashboard/products/9NPHPGRRCT5H/overview](https://partner.microsoft.com/en-us/dashboard/products/9NPHPGRRCT5H/overview).
8. Create a file `app/android/key.properties` with the following content:
9. Create a file `app/android/key.properties` with the following content:
```plain
storePassword=
@@ -439,12 +410,12 @@ Android, macOS, Windows and Linux if you do not want to use the official ones.
storeFile=
```
9. Build the app for Android by running `flutter build appbundle`. The build can
be found at `app/build/app/outputs/bundle/release/app-release.aab` and must
be uploaded to
[https://play.google.com/apps/publish](https://play.google.com/apps/publish).
10. Build the app for Android by running `flutter build appbundle`. The build
can be found at `app/build/app/outputs/bundle/release/app-release.aab` and
must be uploaded to
[https://play.google.com/apps/publish](https://play.google.com/apps/publish).
10. Build the app for iOS by running `flutter build ipa`. The build can be found
11. Build the app for iOS by running `flutter build ipa`. The build can be found
at `app/build/ios/archive/Runner.xcarchive` and must be opened in Xcode. In
Xcode the **Validate App** and **Distribute App** options can be used to
upload the build to

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Rico Berger
Copyright (c) 2024 Rico Berger
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View File

@@ -7,9 +7,12 @@ TweetDeck. FeedDeck allows you to follow your favorite feeds in one place on all
platforms.
<p>
<a href="https://feeddeck.app/download" target="_blank"><img src=".github/assets/badge-app-store.png" height="50"></a>
<a href="https://feeddeck.app/download" target="_blank"><img src=".github/assets/badge-google-play.png" height="50"></a>
<a href="https://feeddeck.app/download" target="_self"><img src=".github/assets/badge-desktop.png" height="50"></a>
<a href="https://apps.apple.com/us/app/feeddeck/id6451055362" target="_blank"><img src=".github/assets/badge-app-store.svg" height="50"></a>
<a href="https://play.google.com/store/apps/details?id=app.feeddeck.feeddeck" target="_blank"><img src=".github/assets/badge-google-play.svg" height="50"></a>
<a href="https://app.feeddeck.app" target="_blank"><img src=".github/assets/badge-web.svg" height="50"></a>
<a href="https://apps.apple.com/us/app/feeddeck/id6451055362" target="_blank"><img src=".github/assets/badge-mac-app-store.svg" height="50"></a>
<a href="https://www.microsoft.com/store/apps/9NPHPGRRCT5H" target="_blank"><img src=".github/assets/badge-windows-store.svg" height="50"></a>
<a href="https://flathub.org/en/apps/app.feeddeck.feeddeck" target="_blank"><img src=".github/assets/badge-flathub.svg" height="50"></a>
</p>
<img src=".github/assets/screenshot.png" width="100%" />
@@ -28,8 +31,8 @@ platforms. FeedDeck is written in [Flutter](https://flutter.dev/) and uses
- **RSS and Social Media Feeds:** Follow your favorite RSS and social media
feeds.
- **News:** Get the latest news from your favorite RSS feeds and Google News.
- **Social Media:** Follow your friends and favorite topics on Medium, Nitter,
Reddit, Tumblr and X.
- **Social Media:** Follow your friends and favorite topics on Medium, Reddit
and Tumblr.
- **GitHub:** Get your GitHub notifications and follow your repository
activities.
- **Podcasts:** Follow and listen to your favorite podcasts, via the built-in

1
app/.gitignore vendored
View File

@@ -31,6 +31,7 @@ migrate_working_dir/
.pub-cache/
.pub/
/build/
/coverage
# Symbolication related
app.*.symbols

View File

@@ -1,3 +1,9 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
@@ -12,11 +18,6 @@ if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
@@ -27,21 +28,18 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
namespace "app.feeddeck.feeddeck"
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = '17'
}
sourceSets {
@@ -49,14 +47,13 @@ android {
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "app.feeddeck.feeddeck"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
// minSdkVersion flutter.minSdkVersion
// targetSdkVersion flutter.targetSdkVersion
minSdkVersion 21
targetSdkVersion 33
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
@@ -72,7 +69,12 @@ android {
buildTypes {
release {
signingConfig signingConfigs.release
if (keystorePropertiesFile.exists()) {
signingConfig signingConfigs.release
} else {
// For testing purposes we sign with dummy credentials if no key properties are given.
signingConfig signingConfigs.debug
}
}
}
}
@@ -82,6 +84,5 @@ flutter {
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.android.gms:play-services-auth:20.6.0'
}

View File

@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.feeddeck.feeddeck">
<application
android:label="feeddeck"
android:label="FeedDeck"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -5,6 +5,10 @@
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your

View File

@@ -1,16 +1,3 @@
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
@@ -26,6 +13,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip

View File

@@ -1,11 +1,26 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.1.2" apply false
id "org.jetbrains.kotlin.android" version "1.9.10" apply false
}
include ":app"

View File

@@ -0,0 +1 @@
extensions:

Binary file not shown.

View File

@@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>

View File

@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'
platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

View File

@@ -8,27 +8,40 @@ PODS:
- Flutter (1.0.0)
- flutter_native_splash (0.0.1):
- Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- just_audio (0.0.1):
- Flutter
- media_kit_libs_ios_video (1.0.4):
- Flutter
- media_kit_native_event_loop (1.0.0):
- Flutter
- media_kit_video (0.0.1):
- Flutter
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- purchases_flutter (6.30.2):
- Flutter
- PurchasesHybridCommon (= 11.1.0)
- PurchasesHybridCommon (11.1.0):
- RevenueCat (= 4.43.2)
- RevenueCat (4.43.2)
- screen_brightness_ios (0.1.0):
- Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sign_in_with_apple (0.0.1):
- Flutter
- sqflite (0.0.2):
- sqflite (0.0.3):
- Flutter
- FMDB (>= 2.7.5)
- FlutterMacOS
- url_launcher_ios (0.0.1):
- Flutter
- webview_flutter_wkwebview (0.0.1):
- volume_controller (0.0.1):
- Flutter
- wakelock_plus (0.0.1):
- Flutter
DEPENDENCIES:
@@ -38,17 +51,24 @@ DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- just_audio (from `.symlinks/plugins/just_audio/ios`)
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
- media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`)
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
- screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
- volume_controller (from `.symlinks/plugins/volume_controller/ios`)
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
SPEC REPOS:
trunk:
- FMDB
- PurchasesHybridCommon
- RevenueCat
EXTERNAL SOURCES:
app_links:
@@ -63,37 +83,56 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_native_splash/ios"
just_audio:
:path: ".symlinks/plugins/just_audio/ios"
media_kit_libs_ios_video:
:path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
media_kit_native_event_loop:
:path: ".symlinks/plugins/media_kit_native_event_loop/ios"
media_kit_video:
:path: ".symlinks/plugins/media_kit_video/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
:path: ".symlinks/plugins/path_provider_foundation/darwin"
purchases_flutter:
:path: ".symlinks/plugins/purchases_flutter/ios"
screen_brightness_ios:
:path: ".symlinks/plugins/screen_brightness_ios/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sign_in_with_apple:
:path: ".symlinks/plugins/sign_in_with_apple/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
:path: ".symlinks/plugins/sqflite/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
volume_controller:
:path: ".symlinks/plugins/volume_controller/ios"
wakelock_plus:
:path: ".symlinks/plugins/wakelock_plus/ios"
SPEC CHECKSUMS:
app_links: 5ef33d0d295a89d9d16bb81b0e3b0d5f70d6c875
app_links: e70ca16b4b0f88253b3b3660200d4a10b4ea9795
audio_service: f509d65da41b9521a61f1c404dd58651f265a567
audio_session: 4f3e461722055d21515cf3261b64c973c062f345
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
audio_session: 088d2483ebd1dc43f51d253d4a1c517d9a2e7207
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
purchases_flutter: 42d5544e7730ea89a88cc2f008b7c700fd147052
PurchasesHybridCommon: 4022d5944cb30ec44ba5159e42aa161fe0e30175
RevenueCat: 3d934653b7e8b09af88fd47e9e84cfaf5d0a89ba
screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9
wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1
PODFILE CHECKSUM: 92152382e3e2d8bbf76cfce953216c7c829d94ce
PODFILE CHECKSUM: 016564c560c4c9dbcb210e12c7aa6039072645f1
COCOAPODS: 1.12.1
COCOAPODS: 1.15.2

View File

@@ -10,6 +10,7 @@
11A5CB70E48EE53811F041B1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4F63A76E5CF724D941DA24D /* Pods_Runner.framework */; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
55F35B592ABF74D1007331B3 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55F35B582ABF74D1007331B3 /* StoreKit.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
@@ -34,6 +35,7 @@
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
551175C42A39020E00A80299 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
55F35B582ABF74D1007331B3 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
5C1B3914BEEA60B960FC050D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -56,6 +58,7 @@
buildActionMask = 2147483647;
files = (
11A5CB70E48EE53811F041B1 /* Pods_Runner.framework in Frameworks */,
55F35B592ABF74D1007331B3 /* StoreKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -121,6 +124,7 @@
AC99711BA86FAD05300ADB7E /* Frameworks */ = {
isa = PBXGroup;
children = (
55F35B582ABF74D1007331B3 /* StoreKit.framework */,
E4F63A76E5CF724D941DA24D /* Pods_Runner.framework */,
);
name = Frameworks;
@@ -157,7 +161,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -228,6 +232,7 @@
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -343,7 +348,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -423,7 +428,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -472,7 +477,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
@@ -20,14 +22,38 @@
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>app.feeddeck.feeddeck</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
@@ -43,31 +69,5 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIStatusBarHidden</key>
<true/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>app.feeddeck.feeddeck</string>
</array>
</dict>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
</dict>
</plist>

View File

@@ -1,21 +1,25 @@
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
import 'package:just_audio_background/just_audio_background.dart';
import 'package:media_kit/media_kit.dart';
import 'package:provider/provider.dart';
import 'package:window_manager/window_manager.dart';
import 'package:feeddeck/repositories/app_repository.dart';
import 'package:feeddeck/repositories/layout_repository.dart';
import 'package:feeddeck/repositories/profile_repository.dart';
import 'package:feeddeck/repositories/settings_repository.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/widgets/confirmation/confirmation.dart';
import 'package:feeddeck/widgets/home/home.dart';
import 'package:feeddeck/widgets/reset_password/reset_password.dart';
import 'package:feeddeck/widgets/item/details/utils/item_audio_palyer/item_audio_player_init/item_audio_player_init.dart';
/// Before we are calling [runApp] we have to ensure that the widget bindings
/// are initialized, so that we can preserve the splash screen until we are done
@@ -44,13 +48,26 @@ void main() async {
});
}
/// Initialize the [media_kit] packages, so that we can play audio and video
/// files.
MediaKit.ensureInitialized();
if (!kIsWeb && (Platform.isLinux || Platform.isWindows)) {
ItemAudioPlayerInit().init();
}
/// Initialize the [just_audio_background] package, so that we can play audio
/// files in the background.
await JustAudioBackground.init(
androidNotificationChannelId: 'com.ryanheise.bg_demo.channel.audio',
androidNotificationChannelName: 'Audio playback',
androidNotificationOngoing: true,
);
///
/// We can not initialize the [just_audio_background] package on Windows and
/// Linux, because then the returned duration in the `_player.durationStream`
/// isn't working correctly in the [ItemAudioPlayer] widget.
if (kIsWeb || Platform.isAndroid || Platform.isIOS || Platform.isMacOS) {
await JustAudioBackground.init(
androidNotificationChannelId: 'com.ryanheise.bg_demo.channel.audio',
androidNotificationChannelName: 'Audio playback',
androidNotificationOngoing: true,
);
}
/// For the ewb we have to use the path url strategy, so that the redirect
/// within Supabase is working in all cases. On all other platforms this is a
@@ -65,6 +82,23 @@ void main() async {
runApp(const FeedDeckApp());
}
/// [FeedDeckScrollBehavior] changes the scrolling behavior of the app. This is
/// required to enable scrolling on desktop via drag, which is the only way that
/// a user can scroll vertically with a mouse via drag.
///
/// E.g. this is required for the [ColumnLayoutSources] widget, where we rely on
/// the drag gesture to scroll the list of sources.
class FeedDeckScrollBehavior extends MaterialScrollBehavior {
@override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
PointerDeviceKind.trackpad,
PointerDeviceKind.stylus,
PointerDeviceKind.unknown,
};
}
/// [onGenerateRoute] is used in `onGenerateRoute` and `onGenerateInitialRoutes`
/// of the [MaterialApp] to add handling for some special routes were do not
/// want to render the [Home] widget (e.g. set a new password).
@@ -106,6 +140,7 @@ class FeedDeckApp extends StatelessWidget {
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => LayoutRepository()),
ChangeNotifierProvider(create: (_) => AppRepository()),
ChangeNotifierProvider(create: (_) => ProfileRepository()),
],
@@ -131,6 +166,7 @@ class FeedDeckApp extends StatelessWidget {
),
canvasColor: Constants.canvasColor,
appBarTheme: const AppBarTheme(
centerTitle: true,
backgroundColor: Constants.appBarBackgroundColor,
scrolledUnderElevation: Constants.scrolledUnderElevation,
elevation: Constants.appBarElevation,
@@ -173,6 +209,7 @@ class FeedDeckApp extends StatelessWidget {
},
),
),
scrollBehavior: FeedDeckScrollBehavior(),
onGenerateInitialRoutes: (initialRoute) =>
[onGenerateRoute(RouteSettings(name: initialRoute))],
onGenerateRoute: (RouteSettings settings) =>

View File

@@ -29,6 +29,40 @@ FDProfileTier getProfileTierFromString(String state) {
return FDProfileTier.free;
}
/// [FDProfileSubscriptionProvider] is a enum value which defines the different
/// subscription providers for a profile. A user can use [stripe] or
/// [revenuecat] to get a premium account.
enum FDProfileSubscriptionProvider {
stripe,
revenuecat,
}
/// [FDProfileSubscriptionProviderExtension] defines all extensions which are
/// available for the [FDProfileSubscriptionProvider] enum type.
extension FDProfileSubscriptionProviderExtension
on FDProfileSubscriptionProvider {
/// [toShortString] returns a short string of the source type which can safely
/// be passed to our database.
String toShortString() {
return toString().split('.').last;
}
}
/// [getSourceTypeFromString] returns the [FDProfileSubscriptionProvider] from
/// his string representation. This is used to parse the JSON value returned by
/// our database into correct enum value in the [FDSource] model.
FDProfileSubscriptionProvider? getProfileSubscriptionProviderFromString(
String state,
) {
for (FDProfileSubscriptionProvider element
in FDProfileSubscriptionProvider.values) {
if (element.toShortString() == state) {
return element;
}
}
return null;
}
/// [FDProfile] is the model for a profile of a user in our app. The following
/// fields are required for a profile:
/// - An [id] to uniquely identify a column in the database
@@ -38,6 +72,7 @@ FDProfileTier getProfileTierFromString(String state) {
class FDProfile {
String id;
FDProfileTier tier;
FDProfileSubscriptionProvider? subscriptionProvider;
bool accountGithub;
int createdAt;
int updatedAt;
@@ -45,6 +80,7 @@ class FDProfile {
FDProfile({
required this.id,
required this.tier,
required this.subscriptionProvider,
required this.accountGithub,
required this.createdAt,
required this.updatedAt,
@@ -54,6 +90,12 @@ class FDProfile {
return FDProfile(
id: data['id'],
tier: getProfileTierFromString(data['tier']),
subscriptionProvider: data.containsKey('subscriptionProvider') &&
data['subscriptionProvider'] != null
? getProfileSubscriptionProviderFromString(
data['subscriptionProvider'],
)
: null,
accountGithub: data['accountGithub'],
createdAt: data['createdAt'],
updatedAt: data['updatedAt'],

View File

@@ -4,20 +4,23 @@ import 'package:feeddeck/models/sources/github.dart';
import 'package:feeddeck/models/sources/googlenews.dart';
import 'package:feeddeck/models/sources/stackoverflow.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/utils/fd_icons.dart';
/// [FDSourceType] is a enum value which defines the source type. A source can
/// have one of the following types:
/// - [fourchan]
/// - [github]
/// - [googlenews]
/// - [lemmy]
/// - [mastodon]
/// - [medium]
/// - [nitter]
/// - [pinterest]
/// - [podcast]
/// - [reddit]
/// - [rss]
/// - [stackoverflow]
/// - [tumblr]
/// - [x]
/// - [youtube]
///
/// The [none] value is not valid and just here as a fallback in case sth. odd
@@ -25,17 +28,19 @@ import 'package:feeddeck/utils/constants.dart';
/// the list, so that we can loop though the types in a ListView / GridView
/// builder via `FDSourceType.values.length - 1`.
enum FDSourceType {
fourchan,
github,
googlenews,
lemmy,
mastodon,
medium,
nitter,
pinterest,
podcast,
reddit,
rss,
stackoverflow,
tumblr,
// x,
youtube,
none,
}
@@ -52,16 +57,22 @@ extension FDSourceTypeExtension on FDSourceType {
/// [toLocalizedString] returns a localized string for a source type.
String toLocalizedString() {
switch (this) {
case FDSourceType.fourchan:
return '4chan';
case FDSourceType.github:
return 'GitHub';
case FDSourceType.googlenews:
return 'Google News';
case FDSourceType.lemmy:
return 'Lemmy';
case FDSourceType.mastodon:
return 'Mastodon';
case FDSourceType.medium:
return 'Medium';
case FDSourceType.nitter:
return 'Nitter';
case FDSourceType.pinterest:
return 'Pinterest';
case FDSourceType.podcast:
return 'Podcast';
case FDSourceType.reddit:
@@ -72,8 +83,6 @@ extension FDSourceTypeExtension on FDSourceType {
return 'StackOverflow';
case FDSourceType.tumblr:
return 'Tumblr';
// case FDSourceType.x:
// return 'X';
case FDSourceType.youtube:
return 'YouTube';
default:
@@ -81,20 +90,61 @@ extension FDSourceTypeExtension on FDSourceType {
}
}
/// [color] returns the brand color for a source type, which can be used as
/// background color for the icon of a source type.
Color get color {
/// [icon] returns the icon for a source.
IconData get icon {
switch (this) {
case FDSourceType.fourchan:
return FDIcons.fourchan;
case FDSourceType.github:
return FDIcons.github;
case FDSourceType.googlenews:
return FDIcons.googlenews;
case FDSourceType.lemmy:
return FDIcons.lemmy;
case FDSourceType.mastodon:
return FDIcons.mastodon;
case FDSourceType.medium:
return FDIcons.medium;
case FDSourceType.nitter:
return FDIcons.nitter;
case FDSourceType.pinterest:
return FDIcons.pinterest;
case FDSourceType.podcast:
return Icons.podcasts;
case FDSourceType.reddit:
return FDIcons.reddit;
case FDSourceType.rss:
return FDIcons.rss;
case FDSourceType.stackoverflow:
return FDIcons.stackoverflow;
case FDSourceType.tumblr:
return FDIcons.tumblr;
case FDSourceType.youtube:
return FDIcons.youtube;
default:
return FDIcons.feeddeck;
}
}
/// [bgColor] returns the background color for the source icon.
Color get bgColor {
switch (this) {
case FDSourceType.fourchan:
return const Color(0xff880000);
case FDSourceType.github:
return const Color(0xff000000);
case FDSourceType.googlenews:
return const Color(0xff4285f4);
case FDSourceType.lemmy:
return const Color(0xff00bc8c);
case FDSourceType.mastodon:
return const Color(0xff6364ff);
case FDSourceType.medium:
return const Color(0xff000000);
case FDSourceType.nitter:
return const Color(0xffff6c60);
case FDSourceType.pinterest:
return const Color(0xffe60023);
case FDSourceType.podcast:
return const Color(0xff872ec4);
case FDSourceType.reddit:
@@ -105,14 +155,49 @@ extension FDSourceTypeExtension on FDSourceType {
return const Color(0xffef8236);
case FDSourceType.tumblr:
return const Color(0xff34526f);
// case FDSourceType.x:
// return const Color(0xff000000);
case FDSourceType.youtube:
return const Color(0xffff0000);
default:
return Constants.primary;
}
}
/// [fgColor] returns the forground color for the source icon. This should be
/// used toether with the [bgColor].
Color get fgColor {
switch (this) {
case FDSourceType.fourchan:
return const Color(0xffffffff);
case FDSourceType.github:
return const Color(0xffffffff);
case FDSourceType.googlenews:
return const Color(0xffffffff);
case FDSourceType.lemmy:
return const Color(0xffffffff);
case FDSourceType.mastodon:
return const Color(0xffffffff);
case FDSourceType.medium:
return const Color(0xffffffff);
case FDSourceType.nitter:
return const Color(0xffffffff);
case FDSourceType.pinterest:
return const Color(0xffffffff);
case FDSourceType.podcast:
return const Color(0xffffffff);
case FDSourceType.reddit:
return const Color(0xffffffff);
case FDSourceType.rss:
return const Color(0xffffffff);
case FDSourceType.stackoverflow:
return const Color(0xffffffff);
case FDSourceType.tumblr:
return const Color(0xffffffff);
case FDSourceType.youtube:
return const Color(0xffffffff);
default:
return Constants.onPrimary;
}
}
}
/// [getSourceTypeFromString] returns the [FDSourceType] from his string
@@ -173,7 +258,7 @@ class FDSource {
'id': id,
'type': type.toShortString(),
'title': title,
'options': options != null ? options!.toJson() : null,
'options': options?.toJson(),
'link': link,
'icon': icon,
};
@@ -183,36 +268,44 @@ class FDSource {
/// [FDSourceOptions] defines all options for the different source types which
/// are available.
class FDSourceOptions {
String? fourchan;
FDGitHubOptions? github;
FDGoogleNewsOptions? googlenews;
String? lemmy;
String? mastodon;
String? medium;
String? nitter;
String? pinterest;
String? podcast;
String? reddit;
String? rss;
FDStackOverflowOptions? stackoverflow;
String? tumblr;
String? x;
String? youtube;
FDSourceOptions({
this.fourchan,
this.github,
this.googlenews,
this.lemmy,
this.mastodon,
this.medium,
this.nitter,
this.pinterest,
this.podcast,
this.reddit,
this.rss,
this.stackoverflow,
this.tumblr,
this.x,
this.youtube,
});
factory FDSourceOptions.fromJson(Map<String, dynamic> responseData) {
return FDSourceOptions(
fourchan: responseData.containsKey('fourchan') &&
responseData['fourchan'] != null
? responseData['fourchan']
: null,
github:
responseData.containsKey('github') && responseData['github'] != null
? FDGitHubOptions.fromJson(responseData['github'])
@@ -221,6 +314,9 @@ class FDSourceOptions {
responseData['googlenews'] != null
? FDGoogleNewsOptions.fromJson(responseData['googlenews'])
: null,
lemmy: responseData.containsKey('lemmy') && responseData['lemmy'] != null
? responseData['lemmy']
: null,
mastodon: responseData.containsKey('mastodon') &&
responseData['mastodon'] != null
? responseData['mastodon']
@@ -233,6 +329,10 @@ class FDSourceOptions {
responseData.containsKey('nitter') && responseData['nitter'] != null
? responseData['nitter']
: null,
pinterest: responseData.containsKey('pinterest') &&
responseData['pinterest'] != null
? responseData['pinterest']
: null,
podcast:
responseData.containsKey('podcast') && responseData['podcast'] != null
? responseData['podcast']
@@ -252,9 +352,6 @@ class FDSourceOptions {
responseData.containsKey('tumblr') && responseData['tumblr'] != null
? responseData['tumblr']
: null,
x: responseData.containsKey('x') && responseData['x'] != null
? responseData['x']
: null,
youtube:
responseData.containsKey('youtube') && responseData['youtube'] != null
? responseData['youtube']
@@ -264,17 +361,19 @@ class FDSourceOptions {
Map<String, dynamic> toJson() {
return {
'fourchan': fourchan,
'github': github?.toJson(),
'googlenews': googlenews?.toJson(),
'lemmy': lemmy,
'mastodon': mastodon,
'medium': medium,
'nitter': nitter,
'pinterest': pinterest,
'podcast': podcast,
'reddit': reddit,
'rss': rss,
'stackoverflow': stackoverflow?.toJson(),
'tumblr': tumblr,
'x': x,
'youtube': youtube,
};
}

View File

@@ -152,7 +152,7 @@ class AppRepository with ChangeNotifier {
.from('decks')
.insert({
'name': name,
'userId': Supabase.instance.client.auth.currentUser!.id
'userId': Supabase.instance.client.auth.currentUser!.id,
})
.select()
.single();
@@ -376,21 +376,33 @@ class AppRepository with ChangeNotifier {
}
/// [addSource] is called to add a source to the column with the provided
/// [columnId]. The function takes a [source] as parameter. The function calls
/// the `add-source-v1` edge function via the Supabase client to create the
/// source. When the source was created the newly returned source is added to
/// the list of sources of the column with the provided [columnId].
/// [columnId]. Next to [columnId] a user must also provide the [type] and
/// [options] for the source. The function calls the `add-or-update-source-v1`
/// edge function via the Supabase client to create the source. When the
/// source was created the newly returned source is added to the list of
/// sources of the column with the provided [columnId].
///
/// The optional [feedData] parameter is used to provide the feed data for the
/// source. This is can be used to scrape the source data via the client (app)
/// instead of the server (scheduler / worker).
Future<void> addSource(
String columnId,
FDSourceType type,
FDSourceOptions options,
) async {
FDSourceOptions options, [
String? feedData,
]) async {
final result = await Supabase.instance.client.functions.invoke(
'add-source-v1',
'add-or-update-source-v1',
body: {
'columnId': columnId,
'type': type.toShortString(),
'options': options.toJson(),
'source': {
'id': '',
'columnId': columnId,
'userId': '',
'type': type.toShortString(),
'title': '',
'options': options.toJson(),
},
'feedData': feedData,
},
);

View File

@@ -105,9 +105,9 @@ class ItemsRepository with ChangeNotifier {
Future<void> _init() async {
final state = ItemsRepositoryStore().get(column.identifier());
if (state != null) {
_status = ItemsStatus.loaded;
_items.addAll(state.items);
_status = state.status;
_filters = state.filters;
_items.addAll(state.items);
notifyListeners();
} else {
await _getItems();
@@ -141,7 +141,7 @@ class ItemsRepository with ChangeNotifier {
/// selected source which is stored in the [_filters.sourceIdFilter]
/// field.
if (_filters.sourceIdFilter != '') {
filter = filter.eq('sourceId', sourceIdFilter);
filter = filter.eq('sourceId', _filters.sourceIdFilter);
}
filter = filter.lte('createdAt', _filters.createdAtFilter);
@@ -168,7 +168,7 @@ class ItemsRepository with ChangeNotifier {
/// filter to page through all the items.
final data = await filter
.order('publishedAt')
.range(_filters.offsetFilter, _filters.offsetFilter + 50);
.range(_filters.offsetFilter, _filters.offsetFilter + 50 - 1);
/// The returned items are added to the [_items] field and the status is
/// set to [ItemsStatus.loaded] or [ItemsStatus.loadedLast] based on the
@@ -189,7 +189,12 @@ class ItemsRepository with ChangeNotifier {
/// Finally we store the state of the repository, so that we do not have
/// to retrieve the items from the database again when therepository is
/// reinitialized.
ItemsRepositoryStore().set(column.identifier(), _items, _filters);
ItemsRepositoryStore().set(
column.identifier(),
_status,
_filters,
_items,
);
notifyListeners();
} catch (_) {
_status = ItemsStatus.loaded;
@@ -278,7 +283,7 @@ class ItemsRepository with ChangeNotifier {
}
}
ItemsRepositoryStore().set(column.id, _items, _filters);
ItemsRepositoryStore().set(column.id, _status, _filters, _items);
notifyListeners();
} catch (err) {
rethrow;
@@ -288,18 +293,27 @@ class ItemsRepository with ChangeNotifier {
/// [updateReadStates] can be used to mark a list of items provided via their
/// [itemIds] as read / unread. When the [read] value is `true` items are
/// marked as read and when it is `false` as unread.
///
/// We have to split the provided list of [itemIds] into chunks of 25 items,
/// to avoid the request uri to long error from Supabase. We decided to use 25
/// items per chunk, because we think that this is a good tradeoff between the
/// number of requests and the number of items we can update at once.
Future<void> updateReadStates(List<String> itemIds, bool read) async {
try {
await Supabase.instance.client
.from('items')
.update({'isRead': read}).in_('id', itemIds);
for (var i = 0; i < _items.length; i++) {
if (itemIds.contains(_items[i].id)) {
_items[i].isRead = read;
final chunks = itemIds.slices(25).toList();
for (var i = 0; i < chunks.length; i++) {
await Supabase.instance.client
.from('items')
.update({'isRead': read}).inFilter('id', chunks[i]);
for (var j = 0; j < _items.length; j++) {
if (chunks[i].contains(_items[j].id)) {
_items[j].isRead = read;
}
}
}
ItemsRepositoryStore().set(column.id, _items, _filters);
ItemsRepositoryStore().set(column.id, _status, _filters, _items);
notifyListeners();
} catch (err) {
rethrow;
@@ -321,7 +335,7 @@ class ItemsRepository with ChangeNotifier {
}
}
ItemsRepositoryStore().set(column.id, _items, _filters);
ItemsRepositoryStore().set(column.id, _status, _filters, _items);
notifyListeners();
} catch (err) {
rethrow;
@@ -333,12 +347,14 @@ class ItemsRepository with ChangeNotifier {
/// in the [ItemsRepositoryStore]. The state contains all the loaded [items] and
/// the [filters] set by user to load the items.
class ItemsRepositoryStoreState {
List<FDItem> items;
ItemsStatus status;
ItemsFilters filters;
List<FDItem> items;
ItemsRepositoryStoreState({
required this.items,
required this.status,
required this.filters,
required this.items,
});
}
@@ -353,7 +369,7 @@ class ItemsRepositoryStore {
static final ItemsRepositoryStore _instance =
ItemsRepositoryStore._internal();
final Map<String, ItemsRepositoryStoreState> itemsRepositoryStoreStates = {};
final Map<String, ItemsRepositoryStoreState> _itemsRepositoryStoreStates = {};
factory ItemsRepositoryStore() {
return _instance;
@@ -366,7 +382,7 @@ class ItemsRepositoryStore {
/// returns `null` to indicate that we have to get the items from the
/// database.
ItemsRepositoryStoreState? get(String columnId) {
return itemsRepositoryStoreStates[columnId];
return _itemsRepositoryStoreStates[columnId];
}
/// [set] saves the [items] and [filters] for a [columnId] in the store. This
@@ -375,10 +391,23 @@ class ItemsRepositoryStore {
///
/// The best is to call the [set] function right before we call
/// `notifyListeners` in the repository.
set(String columnId, List<FDItem> items, ItemsFilters filters) {
return itemsRepositoryStoreStates[columnId] = ItemsRepositoryStoreState(
items: items,
set(
String columnId,
ItemsStatus status,
ItemsFilters filters,
List<FDItem> items,
) {
return _itemsRepositoryStoreStates[columnId] = ItemsRepositoryStoreState(
status: status,
filters: filters,
items: items,
);
}
/// [clear] deletes all the stored [_itemsRepositoryStoreStates] from the
/// store. This method can be used to clear the cache, e.g. when a user
/// changes the active deck or signes out.
clear() {
_itemsRepositoryStoreStates.clear();
}
}

View File

@@ -0,0 +1,12 @@
import 'package:flutter/foundation.dart';
/// The [LayoutRepository] is used to store several layout information of the
/// app, which can be modifed or should be modifed within different locations.
class LayoutRepository with ChangeNotifier {
/// [_deckLayoutSmallInitialTabIndex] stores the selected tab index of the
/// [DeckLayoutSmall] widget. This is used that we display the same tab when
/// a user switches between the small and large layout (e.g. portrait and
/// landscape mode on mobile devices) and that we can reset the tab index when
/// a user selects a new deck.
int deckLayoutSmallInitialTabIndex = 0;
}

View File

@@ -5,7 +5,6 @@ import 'package:flutter/foundation.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:feeddeck/models/profile.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/utils/api_exception.dart';
enum FDProfileStatus {
@@ -13,14 +12,21 @@ enum FDProfileStatus {
initialized,
}
/// The [ProfileRepository] is used to fetch and update a users profile data.
/// The users profile contains all the required information for the users
/// subscription status and the users connected accounts.
class ProfileRepository with ChangeNotifier {
FDProfileStatus _status = FDProfileStatus.uninitialized;
FDProfile? _profile;
FDProfileStatus get status => _status;
FDProfileTier get tier => _profile?.tier ?? FDProfileTier.free;
FDProfileSubscriptionProvider? get subscriptionProvider =>
_profile?.subscriptionProvider;
bool get accountGithub => _profile?.accountGithub ?? false;
/// [init] is used to fetch the users profile from the `profile-v2` edge
/// function.
Future<void> init(bool force) async {
if (_status == FDProfileStatus.initialized && force == false) {
return;
@@ -28,7 +34,7 @@ class ProfileRepository with ChangeNotifier {
try {
final result = await Supabase.instance.client.functions.invoke(
'profile-v1',
'profile-v2/getProfile',
method: HttpMethod.get,
);
@@ -45,16 +51,25 @@ class ProfileRepository with ChangeNotifier {
}
}
Future<void> addGithubAccount(String token) async {
/// [setTier] is used to update the users tier. We do not have to make an API
/// call to update the tier in the database, because this is done via Webhooks
/// by the connected payment provider.
///
/// This is only required to reflect the update in the Flutter app.
void setTier(FDProfileTier tier) {
_profile?.tier = tier;
notifyListeners();
}
/// [githubAddAccount] is used to add a GitHub account to the users profile.
/// For this the user must provide an private access token with the required
/// scopes.
Future<void> githubAddAccount(String token) async {
final result = await Supabase.instance.client.functions.invoke(
'profile-v1',
'profile-v2/githubAddAccount',
method: HttpMethod.post,
body: {
'action': 'add-account',
'sourceType': FDSourceType.github.toShortString(),
'options': {
'token': token,
}
'token': token,
},
);
@@ -66,14 +81,12 @@ class ProfileRepository with ChangeNotifier {
notifyListeners();
}
Future<void> deleteGithubAccount() async {
/// [githubDeleteAccount] deletes the users connected GitHub account. For that
/// we delete the GitHub access token from the database.
Future<void> githubDeleteAccount() async {
final result = await Supabase.instance.client.functions.invoke(
'profile-v1',
method: HttpMethod.post,
body: {
'action': 'delete-account',
'sourceType': FDSourceType.github.toShortString(),
},
'profile-v2/githubDeleteAccount',
method: HttpMethod.delete,
);
if (result.status != 200) {

View File

@@ -17,7 +17,19 @@ class SettingsRepository {
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Iml0eWp1Y3BzcmFzYXZyaWVwc2NyIiwicm9sZSI6ImFub24iLCJpYXQiOjE2OTQwMjY0NjIsImV4cCI6MjAwOTYwMjQ2Mn0.IDo7j9Kh8-5kHLtrZtHTvLf8lUkj7jiLynpIXSZbRFs';
String supabaseSiteUrl = 'https://app.feeddeck.app';
String googleClientId =
'420185423235-9ehth1eodl4lt3cdns7kaf2e89eo6rkq.apps.googleusercontent.com';
'296452997087-2o1qasg1gdbe39b1l39dds1doq3t6h2e.apps.googleusercontent.com';
/// By default the [subscriptionEnabled] variable is set to `true`, so that a
/// user can subscribe to FeedDeck Premium. If the variable is set to `false`
/// the user can not subscribe to FeedDeck Premium.
bool subscriptionEnabled = true;
/// The [revenueCatAppStoreKey] and [revenueCatGooglePlayKey] are used for the
/// in-app purchases. The [revenueCatAppStoreKey] is used for the Apple App
/// Store on iOS and macOS. The [revenueCatGooglePlayKey] is used for the
/// Google Play Store on Android.
final String revenueCatAppStoreKey = 'appl_kThbIaMkylDBtCEmsfczvgCBram';
final String revenueCatGooglePlayKey = 'goog_tBFPbLbygjioviXRIlGlmUOKZYA';
factory SettingsRepository() {
return _instance;
@@ -52,11 +64,16 @@ class SettingsRepository {
googleClientIdPrefs != null) {
/// Store the user provided values within the [SettingsRepository] and
/// use them to initialize the Supabase client.
///
/// Also set the [subscriptionEnabled] variabel to `false`, so that the
/// user can not subscribe to FeedDeck Premium.
supabaseUrl = supabaseUrlPrefs;
supabaseAnonKey = supabaseAnonKeyPrefs;
supabaseSiteUrl = supabaseSiteUrlPrefs;
googleClientId = googleClientIdPrefs;
subscriptionEnabled = false;
await Supabase.initialize(
url: supabaseUrlPrefs,
anonKey: supabaseAnonKeyPrefs,

View File

@@ -56,15 +56,15 @@ const _htmlAuthFinished = '''
</html>
''';
/// The [DesktopLoginManager] is used to authenticate a user with the provided
/// The [DesktopSignInManager] is used to authenticate a user with the provided
/// OAuth [provider] on desktop platforms.
class DesktopLoginManager {
final supabase.Provider provider;
class DesktopSignInManager {
final supabase.OAuthProvider provider;
final Map<String, String>? queryParams;
HttpServer? redirectServer;
DesktopLoginManager({
DesktopSignInManager({
required this.provider,
required this.queryParams,
});

View File

@@ -1,5 +1,7 @@
import 'package:flutter/widgets.dart';
/// Flutter icons FDIcons
/// Copyright (C) 2023 by original authors @ fluttericon.com, fontello.com
/// Copyright (C) 2024 by original authors @ fluttericon.com, fontello.com
/// This font was generated by FlutterIcon.com, which is derived from Fontello.
///
/// To use this font, place it in your fonts/ directory and include the
@@ -11,11 +13,6 @@
/// fonts:
/// - asset: fonts/FDIcons.ttf
///
///
///
import 'package:flutter/widgets.dart';
class FDIcons {
FDIcons._();
@@ -32,6 +29,8 @@ class FDIcons {
IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData googlenews =
IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData pinterest =
IconData(0xe805, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData medium =
IconData(0xe806, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData nitter =
@@ -64,4 +63,8 @@ class FDIcons {
IconData(0xe814, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData mastodon =
IconData(0xe815, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData lemmy =
IconData(0xe816, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData fourchan =
IconData(0xe817, fontFamily: _kFontFam, fontPackage: _kFontPkg);
}

View File

@@ -0,0 +1,55 @@
import 'package:http/http.dart' as http;
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/utils/api_exception.dart';
/// [getFeed] returns the feed for the provided [sourceType] and [options]. It
/// can be used to fetch the feed for a source on the client side (app) instead
/// of via the corresponding `add-or-update-source-v1` edge function or via our
/// worker.
///
/// The functions for the different sources must implement the same parsing for
/// the source options as it is done in the edge function.
Future<String> getFeed(FDSourceType sourceType, FDSourceOptions options) async {
switch (sourceType) {
case FDSourceType.reddit:
return getFeedReddit(options.reddit);
default:
throw const ApiException('Unknown source type', 400);
}
}
/// [getFeedReddit] returns the feed for the provided [input]. It is used to
/// fetch the RSS feed for a Reddit source, which can be passed to the
/// `add-or-update-source-v1` edge function.
///
/// The function must implement the same parsing logic as it is done in the
/// `supabase/functions/_shared/feed/reddit.ts` file.
Future<String> getFeedReddit(String? input) async {
if (input == null || input.isEmpty) {
throw const ApiException('No input provided', 400);
}
String url = '';
try {
if (input.startsWith('/r/') || input.startsWith('/u/')) {
url = 'https://www.reddit.com$input.rss';
} else {
final inputUri = Uri.parse(input);
if (inputUri.host.endsWith('reddit.com')) {
if (input.endsWith('.rss')) {
url = input;
} else {
url = '$input.rss';
}
} else {
throw const ApiException('Invalid input', 400);
}
}
} catch (err) {
throw const ApiException('Invalid input', 400);
}
final response = await http.get(Uri.parse(url));
return response.body;
}

View File

@@ -1,32 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:feeddeck/repositories/settings_repository.dart';
/// [FDImageType] is a enum value which defines the image type. An image can be
/// related to an item or a source.
enum FDImageType {
item,
source,
}
/// [getImageUrl] returns the correct image url to use for the provided image
/// url:
/// - If the [imageType] is [FDImageType.source] the image is always requested
/// from the Supabase storage.
/// - If the [imageType] is [FDImageType.item] and the app runs on the web, the
/// image is proxied through the Supabase functions.
/// - If the [imageType] is [FDImageType.item] and the app runs on a mobile or
/// desktop device, the image is requested directly from the provided url.
String getImageUrl(FDImageType imageType, String imageUrl) {
if (imageType == FDImageType.source) {
return '${SettingsRepository().supabaseUrl}/storage/v1/object/public/sources/$imageUrl';
}
if (kIsWeb) {
return '${Supabase.instance.client.functionsUrl}/image-proxy-v1?media=${Uri.encodeQueryComponent(imageUrl)}';
}
return imageUrl;
}

View File

@@ -0,0 +1,33 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
/// [signInWithApple] performs Apple sign in on iOS and macOS.
/// See https://supabase.com/docs/guides/auth/social-login/auth-apple?platform=flutter#using-native-sign-in-with-apple-in-flutter
Future<AuthResponse> signInWithApple() async {
final rawNonce = Supabase.instance.client.auth.generateRawNonce();
final hashedNonce = sha256.convert(utf8.encode(rawNonce)).toString();
final credential = await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
nonce: hashedNonce,
);
final idToken = credential.identityToken;
if (idToken == null) {
throw const AuthException(
'Could not find ID Token from generated credential.',
);
}
return Supabase.instance.client.auth.signInWithIdToken(
provider: OAuthProvider.apple,
idToken: idToken,
nonce: rawNonce,
);
}

View File

@@ -121,7 +121,7 @@ class _ColumnLayoutHeaderState extends State<ColumnLayoutHeader> {
),
Text(
Characters(
'${items.column.sources.length} ${items.column.sources.length == 1 ? 'Source' : 'Sources'} / ${items.items.length} ${items.items.length == 1 ? 'Item' : 'Items'}',
'${items.column.sources.length} ${items.column.sources.length == 1 ? 'Source' : 'Sources'} / ${items.items.length}${items.status == ItemsStatus.loaded ? '+' : ''} ${items.items.length == 1 ? 'Item' : 'Items'}',
)
.replaceAll(
Characters(''),

View File

@@ -100,7 +100,7 @@ class ColumnLayoutHeaderSettings extends StatelessWidget {
icon: const Icon(Icons.chevron_right),
),
],
)
),
],
);
}

View File

@@ -91,6 +91,7 @@ class _ColumnLayoutHeaderSettingsDeleteColumnState
await Provider.of<AppRepository>(context, listen: false)
.deleteColumn(widget.column.id);
} catch (_) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
duration: Duration(seconds: 10),

View File

@@ -112,6 +112,64 @@ class _CreateDeckState extends State<CreateDeck> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(
bottom: Constants.spacingMiddle,
),
child: RichText(
textAlign: TextAlign.center,
text: const TextSpan(
style: TextStyle(
color: Constants.onSurface,
fontSize: 14.0,
),
children: [
TextSpan(
text: 'We\'re excited to have you onboard at ',
),
TextSpan(
text: 'FeedDeck',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
TextSpan(
text:
'. We hope you enjoy your journey with us. If you have any questions or need assistance, feel free to reach out.',
),
],
),
),
),
Padding(
padding: const EdgeInsets.only(
bottom: Constants.spacingMiddle,
),
child: RichText(
textAlign: TextAlign.center,
text: const TextSpan(
style: TextStyle(
color: Constants.onSurface,
fontSize: 14.0,
),
children: [
TextSpan(
text:
'Now it\'s time to create your first deck. A deck is a collection of columns and sources. Provide the name for your first deck and click on the ',
),
TextSpan(
text: '"Create Deck"',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
TextSpan(
text: ' button.',
),
],
),
),
),
TextFormField(
controller: _nameController,
keyboardType: TextInputType.text,

View File

@@ -5,6 +5,7 @@ import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/repositories/app_repository.dart';
import 'package:feeddeck/repositories/layout_repository.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/widgets/column/column_layout.dart';
import 'package:feeddeck/widgets/column/create/create_column.dart';
@@ -195,9 +196,9 @@ class _DeckLayoutLargeState extends State<DeckLayoutLarge> {
/// The drawer is used to display the [CreateColumn] widget, so that a
/// user can add a new column without leaving the screen.
drawer: ClipRRect(
borderRadius: const BorderRadius.vertical(
top: Radius.circular(Constants.spacingMiddle),
bottom: Radius.circular(Constants.spacingMiddle),
borderRadius: const BorderRadius.only(
topRight: Radius.circular(Constants.spacingMiddle),
bottomRight: Radius.circular(Constants.spacingMiddle),
),
child: Drawer(
width: Constants.columnWidth,
@@ -224,10 +225,20 @@ class _DeckLayoutLargeState extends State<DeckLayoutLarge> {
backgroundColor: Constants.background,
selectedIndex: null,
/// When a user selects a destination in the navigation rail
/// we scroll to the corresponding column by using the
/// `scroll_to_index` package.
/// When a user selects a destination in the navigation
/// rail we scroll to the corresponding column by using
/// the `scroll_to_index` package.
onDestinationSelected: (int index) {
/// Before we scroll to the corresponding column, we
/// also update the [deckLayoutSmallInitialTabIndex] in
/// the [LayoutRepository] so that the correct tab is
/// also selected when a user switches to the small
/// layout.
Provider.of<LayoutRepository>(
context,
listen: false,
).deckLayoutSmallInitialTabIndex = index;
_scrollController.scrollToIndex(
index,
preferPosition: AutoScrollPosition.end,
@@ -244,8 +255,8 @@ class _DeckLayoutLargeState extends State<DeckLayoutLarge> {
/// We add two additional items to the navigation rail via
/// the trailing property. These items are used to allow a
/// user to create a new column and to go to the settings of
/// the app.
/// user to create a new column and to go to the settings
/// of the app.
trailing: Expanded(
child: Align(
alignment: Alignment.bottomCenter,

View File

@@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/repositories/app_repository.dart';
import 'package:feeddeck/repositories/layout_repository.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/widgets/column/column_layout.dart';
import 'package:feeddeck/widgets/column/create/create_column.dart';
@@ -20,6 +21,30 @@ import 'package:feeddeck/widgets/source/source_icon.dart';
class DeckLayoutSmall extends StatelessWidget {
const DeckLayoutSmall({super.key});
/// [_getInitialIndex] returns the initial index for the
/// [DefaultTabController]. The intial index is saved in the
/// [LayoutRepository] so that we can use it when a user switches between the
/// small and large layout or between decks. To not run into errors we have to
/// check that a column which should be used was not already deleted by a
/// user before returning the index. If a column was deleted we reset the
/// index to 0.
int _getInitialIndex(BuildContext context, int columnsLength) {
final deckLayoutSmallInitialTabIndex = Provider.of<LayoutRepository>(
context,
listen: false,
).deckLayoutSmallInitialTabIndex;
if (deckLayoutSmallInitialTabIndex >= columnsLength) {
Provider.of<LayoutRepository>(
context,
listen: false,
).deckLayoutSmallInitialTabIndex = 0;
return 0;
}
return deckLayoutSmallInitialTabIndex;
}
/// [_buildTabs] returns all items for the tab bar. The items are generated
/// by looping thorugh the `columns` defined in the [AppRepository].
///
@@ -124,6 +149,8 @@ class DeckLayoutSmall extends StatelessWidget {
AppRepository app = Provider.of<AppRepository>(context, listen: true);
return DefaultTabController(
key: ValueKey(app.activeDeckId),
initialIndex: _getInitialIndex(context, app.columns.length),
length: app.columns.length,
child: Scaffold(
bottomNavigationBar: SafeArea(
@@ -148,6 +175,18 @@ class DeckLayoutSmall extends StatelessWidget {
),
child: TabBar(
isScrollable: true,
tabAlignment: TabAlignment.start,
dividerHeight: 0,
onTap: (int index) {
/// When the user clicks on a tab we update the index in
/// the [LayoutRepository] so that we can use it as
/// initial index when the widget is rebuild (e.g. when
/// a user switches between the large and small layout).
Provider.of<LayoutRepository>(
context,
listen: false,
).deckLayoutSmallInitialTabIndex = index;
},
tabs: _buildTabs(context),
),
),

View File

@@ -24,7 +24,7 @@ import 'package:flutter/material.dart';
/// ),
/// )
class ElevatedButtonProgressIndicator extends StatelessWidget {
const ElevatedButtonProgressIndicator({Key? key}) : super(key: key);
const ElevatedButtonProgressIndicator({super.key});
@override
Widget build(BuildContext context) {

View File

@@ -39,7 +39,7 @@ class _HomeState extends State<Home> {
});
if (!kIsWeb && (Platform.isIOS || Platform.isAndroid)) {
_appLinks.allUriLinkStream.listen((uri) {
_appLinks.uriLinkStream.listen((uri) {
if (uri
.toString()
.startsWith('app.feeddeck.feeddeck://signin-callback/')) {

View File

@@ -7,9 +7,12 @@ import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/repositories/items_repository.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/utils/openurl.dart';
import 'package:feeddeck/widgets/item/details/item_details_fourchan.dart';
import 'package:feeddeck/widgets/item/details/item_details_lemmy.dart';
import 'package:feeddeck/widgets/item/details/item_details_mastodon.dart';
import 'package:feeddeck/widgets/item/details/item_details_medium.dart';
import 'package:feeddeck/widgets/item/details/item_details_nitter.dart';
import 'package:feeddeck/widgets/item/details/item_details_pinterest.dart';
import 'package:feeddeck/widgets/item/details/item_details_podcast.dart';
import 'package:feeddeck/widgets/item/details/item_details_reddit.dart';
import 'package:feeddeck/widgets/item/details/item_details_rss.dart';
@@ -59,6 +62,12 @@ class ItemDetails extends StatelessWidget {
Widget _buildDetails() {
switch (source.type) {
case FDSourceType.fourchan:
return ItemDetailsFourChan(
item: item,
source: source,
);
/// Sources with type [FDSourceType.github] do not provide a details view,
/// because we directly open the link, when the user clicks on the
/// corresponding preview item.
@@ -70,6 +79,11 @@ class ItemDetails extends StatelessWidget {
/// corresponding preview item.
case FDSourceType.googlenews:
return Container();
case FDSourceType.lemmy:
return ItemDetailsLemmy(
item: item,
source: source,
);
case FDSourceType.mastodon:
return ItemDetailsMastodon(
item: item,
@@ -85,6 +99,11 @@ class ItemDetails extends StatelessWidget {
item: item,
source: source,
);
case FDSourceType.pinterest:
return ItemDetailsPinterest(
item: item,
source: source,
);
case FDSourceType.podcast:
return ItemDetailsPodcast(
item: item,
@@ -110,11 +129,6 @@ class ItemDetails extends StatelessWidget {
item: item,
source: source,
);
// case FDSourceType.x:
// return ItemDetailsX(
// item: item,
// source: source,
// );
case FDSourceType.youtube:
return ItemDetailsYoutube(
item: item,
@@ -196,7 +210,7 @@ class ItemDetails extends StatelessWidget {
Constants.elevatedButtonSize,
),
),
label: const Text('Open link'),
label: const Text('Open Link'),
onPressed: () => _openUrl(item.link),
icon: const Icon(Icons.launch),
),

View File

@@ -2,13 +2,12 @@ import 'package:flutter/material.dart';
import 'package:feeddeck/models/item.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/widgets/item/details/utils/item_description.dart';
import 'package:feeddeck/widgets/item/details/utils/item_media_gallery.dart';
import 'package:feeddeck/widgets/item/details/utils/item_subtitle.dart';
import 'package:feeddeck/widgets/item/details/utils/item_title.dart';
class ItemDetailsX extends StatelessWidget {
const ItemDetailsX({
class ItemDetailsFourChan extends StatelessWidget {
const ItemDetailsFourChan({
super.key,
required this.item,
required this.source,
@@ -23,6 +22,9 @@ class ItemDetailsX extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
ItemTitle(
itemTitle: item.title,
),
ItemSubtitle(
item: item,
source: source,
@@ -32,16 +34,6 @@ class ItemDetailsX extends StatelessWidget {
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
),
const SizedBox(
height: Constants.spacingExtraSmall,
),
ItemMediaGallery(
itemMedias: item.options != null && item.options!.containsKey('media')
? (item.options!['media'] as List)
.map((item) => item as String)
.toList()
: null,
),
],
);
}

View File

@@ -0,0 +1,90 @@
import 'package:flutter/material.dart';
import 'package:feeddeck/models/item.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/widgets/item/details/utils/item_description.dart';
import 'package:feeddeck/widgets/item/details/utils/item_media.dart';
import 'package:feeddeck/widgets/item/details/utils/item_piped/item_piped_video.dart';
import 'package:feeddeck/widgets/item/details/utils/item_subtitle.dart';
import 'package:feeddeck/widgets/item/details/utils/item_title.dart';
import 'package:feeddeck/widgets/item/details/utils/item_videos.dart';
import 'package:feeddeck/widgets/item/details/utils/item_youtube/item_youtube_video.dart';
class ItemDetailsLemmy extends StatelessWidget {
const ItemDetailsLemmy({
super.key,
required this.item,
required this.source,
});
final FDItem item;
final FDSource source;
/// [_buildMedia] builds the media widget for the item. The media widget can
/// display an image, a video or y YouTube video.
///
/// See the `getMedia` function in the `lemmy.ts` file, for a list of
/// extension which are a image / video.
Widget _buildMedia() {
if (item.media != null && item.media! != '') {
final mediaUrl = Uri.parse(item.media!);
if (mediaUrl.path.endsWith('.jpg') ||
mediaUrl.path.endsWith('.jpeg') ||
mediaUrl.path.endsWith('.png') ||
mediaUrl.path.endsWith('.gif')) {
return ItemMedia(
itemMedia: item.media,
);
}
if (mediaUrl.path.endsWith('.mp4')) {
return ItemVideoPlayer(
video: item.media!,
);
}
if (item.media!.startsWith('https://youtu.be/') ||
item.media!.startsWith('https://www.youtube.com/watch?') ||
item.media!.startsWith('https://m.youtube.com/watch?')) {
return ItemYoutubeVideo(
null,
item.media!,
);
}
if (item.media!.startsWith('https://piped.video/watch?v=') ||
item.media!.startsWith('https://piped.video/')) {
return ItemPipedVideo(
null,
item.media!,
);
}
}
return Container();
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
ItemTitle(
itemTitle: item.title,
),
ItemSubtitle(
item: item,
source: source,
),
_buildMedia(),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
),
],
);
}
}

View File

@@ -5,7 +5,10 @@ import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/widgets/item/details/utils/item_description.dart';
import 'package:feeddeck/widgets/item/details/utils/item_media_gallery.dart';
import 'package:feeddeck/widgets/item/details/utils/item_piped/item_piped_video.dart';
import 'package:feeddeck/widgets/item/details/utils/item_subtitle.dart';
import 'package:feeddeck/widgets/item/details/utils/item_videos.dart';
import 'package:feeddeck/widgets/item/details/utils/item_youtube/item_youtube_video.dart';
class ItemDetailsMastodon extends StatelessWidget {
const ItemDetailsMastodon({
@@ -17,6 +20,116 @@ class ItemDetailsMastodon extends StatelessWidget {
final FDItem item;
final FDSource source;
/// [_getYoutubeUrl] returns a YouTube url when the provided [description]
/// contains a YouTube link. If the [description] does not contain a YouTube
/// link, the function returns `null`.
String? _getYoutubeUrl(String description) {
final exp = RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+');
final matches = exp.allMatches(description);
for (var match in matches) {
final url = description.substring(match.start, match.end);
if (url.startsWith('https://youtu.be/') ||
url.startsWith('https://www.youtube.com/watch?') ||
url.startsWith('https://m.youtube.com/watch?')) {
return url;
}
}
return null;
}
/// [_getPipedUrl] returns a Piped url when the provided [description]
/// contains a Piped link. If the [description] does not contain a Piped link,
/// the function returns `null`.
String? _getPipedUrl(String description) {
final exp = RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+');
final matches = exp.allMatches(description);
for (var match in matches) {
final url = description.substring(match.start, match.end);
if (url.startsWith('https://piped.video/watch?v=') ||
url.startsWith('https://piped.video/')) {
return url;
}
}
return null;
}
/// [_buildDescription] builds the description widget for the item. If the
/// description contains a YouTube link, we render the [ItemYoutubeVideo]
/// and the [ItemDescription] widgets. If the description does not contain a
/// YouTube link, we render the [ItemDescription], [ItemMediaGallery] and
/// [ItemVideos] widget.
List<Widget> _buildDescription() {
final youtubeUrl =
item.description != null ? _getYoutubeUrl(item.description!) : null;
if (youtubeUrl != null) {
return [
ItemYoutubeVideo(
item.media,
youtubeUrl,
),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
disableImages: true,
),
];
}
final pipedUrl =
item.description != null ? _getPipedUrl(item.description!) : null;
if (pipedUrl != null) {
return [
ItemPipedVideo(
item.media,
pipedUrl,
),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
disableImages: true,
),
];
}
return [
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
disableImages: true,
),
const SizedBox(
height: Constants.spacingExtraSmall,
),
ItemMediaGallery(
itemMedias: item.options != null &&
item.options!.containsKey('media') &&
item.options!['media'] != null
? (item.options!['media'] as List)
.map((item) => item as String)
.toList()
: null,
),
ItemVideos(
videos: item.options != null &&
item.options!.containsKey('videos') &&
item.options!['videos'] != null
? (item.options!['videos'] as List)
.map((item) => item as String)
.toList()
: null,
),
];
}
@override
Widget build(BuildContext context) {
return Column(
@@ -27,21 +140,7 @@ class ItemDetailsMastodon extends StatelessWidget {
item: item,
source: source,
),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
),
const SizedBox(
height: Constants.spacingExtraSmall,
),
ItemMediaGallery(
itemMedias: item.options != null && item.options!.containsKey('media')
? (item.options!['media'] as List)
.map((item) => item as String)
.toList()
: null,
)
..._buildDescription(),
],
);
}

View File

@@ -5,8 +5,8 @@ import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/widgets/item/details/utils/item_description.dart';
import 'package:feeddeck/widgets/item/details/utils/item_media_gallery.dart';
import 'package:feeddeck/widgets/item/details/utils/item_piped/item_piped_video.dart';
import 'package:feeddeck/widgets/item/details/utils/item_subtitle.dart';
import 'package:feeddeck/widgets/item/details/utils/item_title.dart';
class ItemDetailsNitter extends StatelessWidget {
const ItemDetailsNitter({
@@ -18,18 +18,37 @@ class ItemDetailsNitter extends StatelessWidget {
final FDItem item;
final FDSource source;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
ItemTitle(
itemTitle: item.title,
),
ItemSubtitle(
item: item,
source: source,
/// [_getPipedUrl] returns a Piped url when the provided [description]
/// contains a Piped link. If the [description] does not contain a Piped link,
/// the function returns `null`.
String? _getPipedUrl(String description) {
final exp = RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+');
final matches = exp.allMatches(description);
for (var match in matches) {
final url = description.substring(match.start, match.end);
if (url.startsWith('https://piped.video/watch?v=') ||
url.startsWith('https://piped.video/')) {
return url;
}
}
return null;
}
/// [_buildDescription] builds the description widget for the item. If the
/// description contains a Piped link, we render the [ItemPipedVideo] and the
/// [ItemDescription] widgets. If the description does not contain a Piped
/// link, we render the [ItemDescription] and [ItemMediaGallery] widget.
List<Widget> _buildDescription() {
final pipedUrl =
item.description != null ? _getPipedUrl(item.description!) : null;
if (pipedUrl != null) {
return [
ItemPipedVideo(
item.media,
pipedUrl,
),
ItemDescription(
itemDescription: item.description,
@@ -37,16 +56,40 @@ class ItemDetailsNitter extends StatelessWidget {
tagetFormat: DescriptionFormat.markdown,
disableImages: true,
),
const SizedBox(
height: Constants.spacingExtraSmall,
),
ItemMediaGallery(
itemMedias: item.options != null && item.options!.containsKey('media')
? (item.options!['media'] as List)
.map((item) => item as String)
.toList()
: null,
];
}
return [
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
disableImages: true,
),
const SizedBox(
height: Constants.spacingExtraSmall,
),
ItemMediaGallery(
itemMedias: item.options != null && item.options!.containsKey('media')
? (item.options!['media'] as List)
.map((item) => item as String)
.toList()
: null,
),
];
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
ItemSubtitle(
item: item,
source: source,
),
..._buildDescription(),
],
);
}

View File

@@ -0,0 +1,40 @@
import 'package:flutter/material.dart';
import 'package:feeddeck/models/item.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/widgets/item/details/utils/item_description.dart';
import 'package:feeddeck/widgets/item/details/utils/item_subtitle.dart';
import 'package:feeddeck/widgets/item/details/utils/item_title.dart';
class ItemDetailsPinterest extends StatelessWidget {
const ItemDetailsPinterest({
super.key,
required this.item,
required this.source,
});
final FDItem item;
final FDSource source;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
ItemTitle(
itemTitle: item.title,
),
ItemSubtitle(
item: item,
source: source,
),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
),
],
);
}
}

View File

@@ -1,15 +1,13 @@
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:feeddeck/models/item.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/utils/image_url.dart';
import 'package:feeddeck/widgets/item/details/utils/item_audio_palyer/item_audio_player.dart';
import 'package:feeddeck/widgets/item/details/utils/item_description.dart';
import 'package:feeddeck/widgets/item/details/utils/item_subtitle.dart';
import 'package:feeddeck/widgets/item/details/utils/item_title.dart';
import 'package:feeddeck/widgets/utils/cached_network_image.dart';
class ItemDetailsPodcast extends StatelessWidget {
const ItemDetailsPodcast({
@@ -21,14 +19,6 @@ class ItemDetailsPodcast extends StatelessWidget {
final FDItem item;
final FDSource source;
String? _buildImageUrl() {
if (source.icon != null && source.icon != '') {
return getImageUrl(FDImageType.source, source.icon!);
}
return null;
}
/// [_buildImage] returns an image which is displayed above the
/// [ItemAudioPlayer]. For this image we are using the [source.icon] if it is
/// available. If the [source.icon] is not available, we are not displaying
@@ -55,8 +45,6 @@ class ItemDetailsPodcast extends StatelessWidget {
@override
Widget build(BuildContext context) {
final imageUrl = _buildImageUrl();
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
@@ -74,7 +62,7 @@ class ItemDetailsPodcast extends StatelessWidget {
/// directly listen to the podcast episode.
Column(
children: [
_buildImage(imageUrl),
_buildImage(source.icon),
const SizedBox(
height: Constants.spacingMiddle,
),
@@ -83,7 +71,7 @@ class ItemDetailsPodcast extends StatelessWidget {
audioFile: item.media!,
audioTitle: item.title,
audioArtist: source.title,
audioArt: imageUrl,
audioArt: getImageUrl(source.icon!),
),
const SizedBox(
height: Constants.spacingMiddle,

View File

@@ -3,8 +3,10 @@ import 'package:flutter/material.dart';
import 'package:feeddeck/models/item.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/widgets/item/details/utils/item_description.dart';
import 'package:feeddeck/widgets/item/details/utils/item_piped/item_piped_video.dart';
import 'package:feeddeck/widgets/item/details/utils/item_subtitle.dart';
import 'package:feeddeck/widgets/item/details/utils/item_title.dart';
import 'package:feeddeck/widgets/item/details/utils/item_youtube/item_youtube_video.dart';
class ItemDetailsReddit extends StatelessWidget {
const ItemDetailsReddit({
@@ -16,6 +18,98 @@ class ItemDetailsReddit extends StatelessWidget {
final FDItem item;
final FDSource source;
/// [_getYoutubeUrl] returns a YouTube url when the provided [description]
/// contains a YouTube link. If the [description] does not contain a YouTube
/// link, the function returns `null`.
String? _getYoutubeUrl(String description) {
final exp = RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+');
final matches = exp.allMatches(description);
for (var match in matches) {
final url = description.substring(match.start, match.end);
if (url.startsWith('https://youtu.be/') ||
url.startsWith('https://www.youtube.com/watch?') ||
url.startsWith('https://m.youtube.com/watch?')) {
return url;
}
}
return null;
}
/// [_getPipedUrl] returns a Piped url when the provided [description]
/// contains a Piped link. If the [description] does not contain a Piped link,
/// the function returns `null`.
String? _getPipedUrl(String description) {
final exp = RegExp(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+');
final matches = exp.allMatches(description);
for (var match in matches) {
final url = description.substring(match.start, match.end);
if (url.startsWith('https://piped.video/watch?v=') ||
url.startsWith('https://piped.video/')) {
return url;
}
}
return null;
}
/// [_buildDescription] builds the description widget for the item. If the
/// description contains a YouTube link, we render the [ItemYoutubeVideo]
/// and the [ItemDescription] widgets. If the description contains a Piped
/// link, we render the [ItemPipedVideo] and the [ItemDescription] widget. If
/// the description does not contain a YouTube or Piped link, we only render
/// the [ItemDescription] widget.
///
/// If the description containes a YouTube link we also have to disable the
/// rendering of images within the [ItemDescription] widget.
List<Widget> _buildDescription() {
final youtubeUrl =
item.description != null ? _getYoutubeUrl(item.description!) : null;
if (youtubeUrl != null) {
return [
ItemYoutubeVideo(
item.media,
youtubeUrl,
),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
disableImages: true,
),
];
}
final pipedUrl =
item.description != null ? _getPipedUrl(item.description!) : null;
if (pipedUrl != null) {
return [
ItemPipedVideo(
item.media,
pipedUrl,
),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
disableImages: true,
),
];
}
return [
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
),
];
}
@override
Widget build(BuildContext context) {
return Column(
@@ -29,11 +123,7 @@ class ItemDetailsReddit extends StatelessWidget {
item: item,
source: source,
),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
),
..._buildDescription(),
],
);
}

View File

@@ -1,11 +1,14 @@
import 'package:flutter/material.dart';
import 'package:html/parser.dart' show parse;
import 'package:feeddeck/models/item.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/widgets/item/details/utils/item_description.dart';
import 'package:feeddeck/widgets/item/details/utils/item_media.dart';
import 'package:feeddeck/widgets/item/details/utils/item_subtitle.dart';
import 'package:feeddeck/widgets/item/details/utils/item_title.dart';
import 'package:feeddeck/widgets/item/details/utils/item_videos.dart';
class ItemDetailsRSS extends StatelessWidget {
const ItemDetailsRSS({
@@ -17,6 +20,31 @@ class ItemDetailsRSS extends StatelessWidget {
final FDItem item;
final FDSource source;
/// [_buildMedia] renders an image or video for the item. If the description
/// of the item contains an image we do not render the image, because it could
/// already be rendered via the description.
///
/// Videos are currently always rendered, because they will not be rendered,
/// by the [MarkdownBody] widget.
Widget _buildMedia() {
if (item.options != null &&
item.options!.containsKey('video') &&
item.options!['video'] != null) {
return ItemVideos(videos: [item.options!['video']]);
}
/// Check if the description of the RSS feed contains an image. If this is
/// the case we do not render the image from the [item.media] because the
/// image is already rendered in the [ItemDescription] widget.
if (parse(item.description).querySelectorAll('img').isNotEmpty) {
return Container();
}
return ItemMedia(
itemMedia: item.media,
);
}
@override
Widget build(BuildContext context) {
return Column(
@@ -30,13 +58,11 @@ class ItemDetailsRSS extends StatelessWidget {
item: item,
source: source,
),
ItemMedia(
itemMedia: item.media,
),
_buildMedia(),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.plain,
tagetFormat: DescriptionFormat.plain,
sourceFormat: DescriptionFormat.html,
tagetFormat: DescriptionFormat.markdown,
),
],
);

View File

@@ -1,17 +1,11 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:youtube_player_iframe/youtube_player_iframe.dart';
import 'package:feeddeck/models/item.dart';
import 'package:feeddeck/models/source.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/widgets/item/details/utils/item_description.dart';
import 'package:feeddeck/widgets/item/details/utils/item_media.dart';
import 'package:feeddeck/widgets/item/details/utils/item_subtitle.dart';
import 'package:feeddeck/widgets/item/details/utils/item_title.dart';
import 'package:feeddeck/widgets/item/details/utils/item_youtube/item_youtube_video.dart';
class ItemDetailsYoutube extends StatelessWidget {
const ItemDetailsYoutube({
@@ -23,22 +17,6 @@ class ItemDetailsYoutube extends StatelessWidget {
final FDItem item;
final FDSource source;
/// [_buildMedia] returns the media element for the item. On the web we are
/// using the [YoutubeVideo] widget to render the video, so that a user can
/// directly play the YouTube video. On all other platforms we display the
/// thumbnail of the video.
Widget _buildMedia() {
if (kIsWeb || Platform.isAndroid || Platform.isIOS) {
return YoutubeVideo(
videoUrl: item.link,
);
}
return ItemMedia(
itemMedia: item.media,
);
}
@override
Widget build(BuildContext context) {
return Column(
@@ -52,7 +30,10 @@ class ItemDetailsYoutube extends StatelessWidget {
item: item,
source: source,
),
_buildMedia(),
ItemYoutubeVideo(
item.media,
item.link,
),
ItemDescription(
itemDescription: item.description,
sourceFormat: DescriptionFormat.plain,
@@ -62,51 +43,3 @@ class ItemDetailsYoutube extends StatelessWidget {
);
}
}
class YoutubeVideo extends StatefulWidget {
const YoutubeVideo({
super.key,
required this.videoUrl,
});
final String videoUrl;
@override
State<YoutubeVideo> createState() => _YoutubeVideoState();
}
class _YoutubeVideoState extends State<YoutubeVideo> {
late YoutubePlayerController _controller;
@override
void initState() {
super.initState();
_controller = YoutubePlayerController(
params: const YoutubePlayerParams(
showControls: true,
showFullscreenButton: false,
),
);
_controller.cueVideoByUrl(mediaContentUrl: widget.videoUrl);
_controller.cueVideoById(
videoId: widget.videoUrl.replaceFirst(
'https://www.youtube.com/watch?v=',
'',
),
);
}
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(
bottom: Constants.spacingMiddle,
),
child: YoutubePlayer(
controller: _controller,
aspectRatio: 16 / 9,
),
);
}
}

View File

@@ -65,6 +65,13 @@ class _ItemAudioPlayerState extends State<ItemAudioPlayer> {
@override
void dispose() {
/// We have to dispose the [_player] when the widget is disposed, otherwise
/// the audio will continue to play in the background.
///
/// On Linux and Windows the audio will continue to play even if the
/// [_player] is disposed, so that we also call the `pause` method of the
/// [_player] to stop the audio.
_player.pause();
_player.dispose();
super.dispose();
}

View File

@@ -67,15 +67,8 @@ class ItemAudioPlayerControlButtons extends StatelessWidget {
final playerState = snapshot.data;
final processingState = playerState?.processingState;
final playing = playerState?.playing;
if (processingState == ProcessingState.loading ||
processingState == ProcessingState.buffering) {
return Container(
margin: const EdgeInsets.all(Constants.spacingSmall),
width: 48.0,
height: 48.0,
child: const CircularProgressIndicator(),
);
} else if (playing != true) {
if (playing != true) {
return IconButton(
icon: const Icon(Icons.play_arrow),
iconSize: 64.0,

View File

@@ -0,0 +1,11 @@
library item_audio_player_init;
import 'item_audio_player_init_stub.dart'
if (dart.library.io) 'item_audio_player_init_native.dart'
if (dart.library.html) 'item_audio_player_init_web.dart';
abstract class ItemAudioPlayerInit {
void init();
factory ItemAudioPlayerInit() => getItemAudioPlayerInit();
}

View File

@@ -0,0 +1,12 @@
import 'package:just_audio_media_kit/just_audio_media_kit.dart';
import 'item_audio_player_init.dart';
class ItemAudioPlayerInitNative implements ItemAudioPlayerInit {
@override
void init() {
JustAudioMediaKit.ensureInitialized();
}
}
ItemAudioPlayerInit getItemAudioPlayerInit() => ItemAudioPlayerInitNative();

View File

@@ -0,0 +1,5 @@
import 'item_audio_player_init.dart';
ItemAudioPlayerInit getItemAudioPlayerInit() => throw UnsupportedError(
'Can not ItemAudioPlayerInit without the packages dart:html or dart:io',
);

View File

@@ -0,0 +1,8 @@
import 'item_audio_player_init.dart';
class ItemAudioPlayerInitWeb implements ItemAudioPlayerInit {
@override
void init() {}
}
ItemAudioPlayerInit getItemAudioPlayerInit() => ItemAudioPlayerInitWeb();

View File

@@ -35,6 +35,16 @@ class _ItemAudioPlayerSeekBarState extends State<ItemAudioPlayerSeekBar> {
/// audio file.
Duration get _remaining => widget.duration - widget.position;
/// [_printDuration] prints the provided [duration] in a human readable format
/// `HH:mm:ss`.
String _printDuration(Duration duration) {
String negativeSign = duration.isNegative ? '-' : '';
String twoDigits(int n) => n.toString().padLeft(2, '0');
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60).abs());
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60).abs());
return '$negativeSign${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds';
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
@@ -110,10 +120,7 @@ class _ItemAudioPlayerSeekBarState extends State<ItemAudioPlayerSeekBar> {
left: Constants.spacingMiddle,
bottom: 0.0,
child: Text(
RegExp(r'((^0*[1-9]\d*:)?\d{2}:\d{2})\.\d+$')
.firstMatch('${widget.position}')
?.group(1) ??
'${widget.position}',
_printDuration(widget.position),
style: Theme.of(context).textTheme.bodySmall,
),
),
@@ -121,10 +128,7 @@ class _ItemAudioPlayerSeekBarState extends State<ItemAudioPlayerSeekBar> {
right: Constants.spacingMiddle,
bottom: 0.0,
child: Text(
RegExp(r'((^0*[1-9]\d*:)?\d{2}:\d{2})\.\d+$')
.firstMatch('$_remaining')
?.group(1) ??
'$_remaining',
_printDuration(_remaining),
style: Theme.of(context).textTheme.bodySmall,
),
),

View File

@@ -1,14 +1,12 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:html2md/html2md.dart' as html2md;
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:feeddeck/utils/constants.dart';
import 'package:feeddeck/utils/font.dart';
import 'package:feeddeck/utils/openurl.dart';
import 'package:feeddeck/widgets/utils/cached_network_image.dart';
/// The [DescriptionFormat] enum defines the source and target format of a
/// description.
@@ -47,7 +45,7 @@ class ItemDescription extends StatelessWidget {
Widget _buildMarkdown(BuildContext context, String content) {
return MarkdownBody(
selectable: true,
data: content,
data: content.trim(),
styleSheet: MarkdownStyleSheet(
code: TextStyle(
fontFamily: getMonospaceFontFamily(),
@@ -56,6 +54,15 @@ class ItemDescription extends StatelessWidget {
codeblockDecoration: const BoxDecoration(
color: Constants.secondary,
),
blockquoteDecoration: const BoxDecoration(
color: Constants.secondary,
border: Border(
left: BorderSide(
color: Constants.primary,
width: 1,
),
),
),
),
onTapLink: (text, href, title) {
if (href != null) {
@@ -67,12 +74,6 @@ class ItemDescription extends StatelessWidget {
return Container();
}
String imageUrl = uri.toString();
if (kIsWeb) {
imageUrl =
'${Supabase.instance.client.functionsUrl}/image-proxy-v1?media=${Uri.encodeQueryComponent(imageUrl)}';
}
return Container(
padding: const EdgeInsets.only(
bottom: Constants.spacingMiddle,
@@ -87,6 +88,9 @@ class ItemDescription extends StatelessWidget {
isDismissible: true,
useSafeArea: true,
backgroundColor: Colors.black,
constraints: const BoxConstraints(
maxWidth: double.infinity,
),
builder: (BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
@@ -95,7 +99,7 @@ class ItemDescription extends StatelessWidget {
Center(
child: CachedNetworkImage(
fit: BoxFit.contain,
imageUrl: imageUrl,
imageUrl: uri.toString(),
placeholder: (context, url) => Container(),
errorWidget: (context, url, error) => Container(),
),
@@ -121,7 +125,7 @@ class ItemDescription extends StatelessWidget {
child: CachedNetworkImage(
width: double.infinity,
fit: BoxFit.contain,
imageUrl: imageUrl,
imageUrl: uri.toString(),
placeholder: (context, url) => Container(),
errorWidget: (context, url, error) => Container(),
),
@@ -135,7 +139,7 @@ class ItemDescription extends StatelessWidget {
/// [_buildPlain] renders the provided [content] as plain text.
Widget _buildPlain(String content) {
return SelectableText(
content,
content.trim(),
textAlign: TextAlign.left,
style: const TextStyle(
fontWeight: FontWeight.normal,
@@ -163,7 +167,9 @@ class ItemDescription extends StatelessWidget {
if (sourceFormat == DescriptionFormat.html &&
tagetFormat == DescriptionFormat.plain) {
return _buildPlain(
itemDescription!.replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), ''),
itemDescription!
.replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), ' ')
.replaceAll(RegExp('\\s+'), ' '),
);
}

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