mirror of
https://github.com/immich-app/immich.git
synced 2025-07-09 03:04:16 -04:00
feat(mobile): enabled DCM (#17957)
* enable DCM in CI * chore: up version * chore: up version --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
parent
16f83c0aa9
commit
b890440f6b
12
.github/workflows/static_analysis.yml
vendored
12
.github/workflows/static_analysis.yml
vendored
@ -58,6 +58,14 @@ jobs:
|
||||
run: dart pub get
|
||||
working-directory: ./mobile
|
||||
|
||||
- name: Install DCM
|
||||
run: |
|
||||
sudo apt-get update
|
||||
wget -qO- https://dcm.dev/pgp-key.public | sudo gpg --dearmor -o /usr/share/keyrings/dcm.gpg
|
||||
echo 'deb [signed-by=/usr/share/keyrings/dcm.gpg arch=amd64] https://dcm.dev/debian stable main' | sudo tee /etc/apt/sources.list.d/dart_stable.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install dcm
|
||||
|
||||
- name: Generate translation file
|
||||
run: make translation
|
||||
working-directory: ./mobile
|
||||
@ -100,6 +108,10 @@ jobs:
|
||||
run: dart run custom_lint
|
||||
working-directory: ./mobile
|
||||
|
||||
- name: Run DCM
|
||||
run: dcm analyze lib
|
||||
working-directory: ./mobile
|
||||
|
||||
zizmor:
|
||||
name: zizmor
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -17,6 +17,27 @@ To add a new translation text, enter the key-value pair in the `i18n/en.json` in
|
||||
make translation
|
||||
```
|
||||
|
||||
## Static Analysis
|
||||
|
||||
The following checks of static analysis must pass for a contribution to the mobile app to be valid:
|
||||
|
||||
```bash
|
||||
dart format lib
|
||||
dart analyze
|
||||
dart run custom_lint
|
||||
dcm analyze lib
|
||||
```
|
||||
|
||||
[DCM](https://dcm.dev/) is a vendor tool that needs to be downloaded manually to run locally.
|
||||
Immich was provided an open source license.
|
||||
To use it, it is important that you do not have an active free tier license (can be verified with `dcm license`).
|
||||
If you have write-access to the Immich repository directly, running dcm in your clone should just work.
|
||||
If you are working on a clone of a fork, you need to connect to the main Immich repository as remote first:
|
||||
|
||||
```bash
|
||||
git remote add immich git@github.com:immich-app/immich.git
|
||||
```
|
||||
|
||||
## Immich-Flutter Directory Structure
|
||||
|
||||
Below are the directory inside the `lib` directory:
|
||||
|
@ -128,82 +128,169 @@ custom_lint:
|
||||
- test/**.dart
|
||||
|
||||
dart_code_metrics:
|
||||
extends:
|
||||
- recommended
|
||||
rules:
|
||||
# Common
|
||||
- arguments-ordering:
|
||||
last:
|
||||
- child
|
||||
- children
|
||||
- avoid-accessing-other-classes-private-members
|
||||
- avoid-assigning-to-static-field
|
||||
- avoid-assignments-as-conditions
|
||||
- avoid-async-call-in-sync-function
|
||||
- avoid-collapsible-if
|
||||
- avoid-collection-equality-checks
|
||||
- avoid-complex-loop-conditions
|
||||
- avoid-declaring-call-method
|
||||
- avoid-extensions-on-records
|
||||
- avoid-function-type-in-records
|
||||
- avoid-future-ignore
|
||||
- avoid-global-state
|
||||
- avoid-inverted-boolean-checks
|
||||
- avoid-late-final-reassignment
|
||||
- avoid-local-functions:
|
||||
exclude:
|
||||
- test/**.dart
|
||||
- avoid-negated-conditions
|
||||
- avoid-nested-streams-and-futures
|
||||
- avoid-referencing-subclasses
|
||||
- avoid-unnecessary-continue
|
||||
- avoid-unnecessary-nullable-return-type: false
|
||||
- binary-expression-operand-order
|
||||
- pattern-fields-ordering
|
||||
- prefer-abstract-final-static-class
|
||||
- prefer-commenting-future-delayed
|
||||
- prefer-early-return
|
||||
- prefer-first
|
||||
- prefer-immediate-return
|
||||
- prefer-last
|
||||
- prefer-simpler-boolean-expressions
|
||||
- prefer-switch-expression
|
||||
- prefer-type-over-var
|
||||
- use-existing-destructuring
|
||||
- use-existing-variable
|
||||
# Flutter
|
||||
- avoid-border-all
|
||||
- avoid-complex-arithmetic-expressions
|
||||
- avoid-expanded-as-spacer
|
||||
- avoid-if-with-many-branches
|
||||
- avoid-inherited-widget-in-initstate
|
||||
- avoid-late-context
|
||||
- avoid-returning-widgets
|
||||
- avoid-shrink-wrap-in-lists
|
||||
- avoid-single-child-column-or-row
|
||||
- avoid-stateless-widget-initialized-fields
|
||||
- avoid-wrapping-in-padding
|
||||
- prefer-align-over-container
|
||||
- prefer-const-border-radius
|
||||
- prefer-correct-callback-field-name: false
|
||||
- prefer-correct-edge-insets-constructor
|
||||
- prefer-define-hero-tag
|
||||
- prefer-extracting-callbacks
|
||||
- prefer-for-loop-in-children
|
||||
- prefer-match-file-name: false
|
||||
- prefer-sliver-prefix
|
||||
- prefer-spacing
|
||||
- prefer-text-rich
|
||||
- prefer-transform-over-container
|
||||
- prefer-using-list-view
|
||||
- prefer-widget-private-members:
|
||||
ignore-static: true
|
||||
- use-closest-build-context
|
||||
# riverpod
|
||||
- avoid-calling-notifier-members-inside-build
|
||||
- avoid-notifier-constructors
|
||||
- avoid-ref-read-inside-build
|
||||
- avoid-ref-watch-outside-build
|
||||
- avoid-unnecessary-consumer-widgets
|
||||
- dispose-provided-instances
|
||||
- use-ref-read-synchronously
|
||||
# All rules from "recommended" preset
|
||||
# Show potential errors
|
||||
# - avoid-cascade-after-if-null
|
||||
# - avoid-collection-methods-with-unrelated-types
|
||||
# - avoid-duplicate-exports
|
||||
# - avoid-dynamic
|
||||
# - avoid-missing-enum-constant-in-map
|
||||
# - avoid-passing-async-when-sync-expected
|
||||
# - avoid-throw-in-catch-block
|
||||
- avoid-unused-parameters
|
||||
# - avoid-unnecessary-type-assertions
|
||||
# - avoid-unnecessary-type-casts
|
||||
# - avoid-unrelated-type-assertions
|
||||
# - avoid-unrelated-type-casts
|
||||
# - no-empty-block
|
||||
# - no-equal-then-else
|
||||
# - prefer-correct-test-file-name
|
||||
# - prefer-match-file-name
|
||||
# - prefer-return-await
|
||||
# - avoid-self-assignment
|
||||
# - avoid-self-compare
|
||||
# - avoid-shadowing
|
||||
# - prefer-iterable-of
|
||||
# - no-equal-switch-case
|
||||
# - no-equal-conditions
|
||||
# - avoid-equal-expressions
|
||||
# - avoid-missed-calls
|
||||
# - avoid-unnecessary-negations
|
||||
# - avoid-unused-generics
|
||||
# - function-always-returns-null
|
||||
# - avoid-throw-objects-without-tostring
|
||||
# - avoid-unsafe-collection-methods
|
||||
# - prefer-wildcard-pattern
|
||||
# - no-equal-switch-expression-cases
|
||||
# - avoid-future-tostring
|
||||
# - avoid-unassigned-late-fields
|
||||
# - avoid-nested-futures
|
||||
# - avoid-generics-shadowing
|
||||
# - prefer-parentheses-with-if-null
|
||||
# - no-equal-nested-conditions
|
||||
# - avoid-shadowed-extension-methods
|
||||
# - avoid-unnecessary-conditionals
|
||||
# - avoid-double-slash-imports
|
||||
# - avoid-map-keys-contains
|
||||
# - prefer-correct-json-casts
|
||||
# - avoid-duplicate-mixins
|
||||
# - avoid-nullable-interpolation
|
||||
# - avoid-unused-instances
|
||||
# - prefer-correct-for-loop-increment
|
||||
# - prefer-public-exception-classes
|
||||
# - avoid-uncaught-future-errors
|
||||
# - always-remove-listener
|
||||
# - avoid-unnecessary-setstate
|
||||
# - check-for-equals-in-render-object-setters
|
||||
# - consistent-update-render-object
|
||||
# - use-setstate-synchronously
|
||||
# - avoid-incomplete-copy-with
|
||||
# - proper-super-calls
|
||||
# - dispose-fields
|
||||
# - avoid-empty-setstate
|
||||
# - avoid-state-constructors
|
||||
# - avoid-recursive-widget-calls
|
||||
# - avoid-missing-image-alt
|
||||
# - avoid-passing-self-as-argument
|
||||
# - avoid-unnecessary-if
|
||||
# - avoid-unconditional-break
|
||||
# - avoid-referencing-discarded-variables
|
||||
# - avoid-unnecessary-local-late
|
||||
# - avoid-wildcard-cases-with-enums
|
||||
# - match-getter-setter-field-names
|
||||
# - avoid-accessing-collections-by-constant-index
|
||||
# - prefer-unique-test-names
|
||||
# - avoid-duplicate-cascades
|
||||
# - prefer-specific-cases-first
|
||||
# - avoid-duplicate-switch-case-conditions
|
||||
# - prefer-explicit-function-type
|
||||
# - avoid-misused-test-matchers
|
||||
# - avoid-duplicate-test-assertions
|
||||
# - prefer-switch-with-enums
|
||||
# - prefer-any-or-every
|
||||
# - avoid-duplicate-map-keys
|
||||
# - avoid-nullable-tostring
|
||||
# - avoid-undisposed-instances
|
||||
# - avoid-duplicate-initializers
|
||||
# - avoid-unassigned-stream-subscriptions
|
||||
# - avoid-empty-test-groups
|
||||
# - avoid-not-encodable-in-to-json
|
||||
# - avoid-contradictory-expressions
|
||||
# - avoid-excessive-expressions
|
||||
# - prefer-private-extension-type-field
|
||||
# - avoid-renaming-representation-getters
|
||||
# - avoid-empty-spread
|
||||
# - avoid-unnecessary-gesture-detector
|
||||
# - avoid-missing-completer-stack-trace
|
||||
# - avoid-casting-to-extension-type
|
||||
# - prefer-overriding-parent-equality
|
||||
# - avoid-missing-controller
|
||||
# - avoid-unknown-pragma
|
||||
# - avoid-conditions-with-boolean-literals
|
||||
# - avoid-multi-assignment
|
||||
# - avoid-collection-equality-checks
|
||||
# - avoid-only-rethrow
|
||||
# - avoid-incorrect-image-opacity
|
||||
# - avoid-misused-set-literals
|
||||
# - dispose-class-fields
|
||||
# - avoid-suspicious-super-overrides
|
||||
# - avoid-assignments-as-conditions
|
||||
# - avoid-unused-assignment
|
||||
# - avoid-unnecessary-overrides
|
||||
# - avoid-implicitly-nullable-extension-types
|
||||
# Enable with the next release
|
||||
# - avoid-late-final-reassignment
|
||||
# - avoid-duplicate-constant-values
|
||||
# - function-always-returns-same-value
|
||||
# - avoid-flexible-outside-flex
|
||||
# - avoid-unnecessary-patterns
|
||||
# - use-closest-build-context
|
||||
# - avoid-commented-out-code
|
||||
# - avoid-recursive-tostring
|
||||
# - avoid-enum-values-by-index
|
||||
# - avoid-constant-assert-conditions
|
||||
# - avoid-inconsistent-digit-separators
|
||||
# - pass-existing-future-to-future-builder
|
||||
# - pass-existing-stream-to-stream-builder
|
||||
|
||||
# Code simplification
|
||||
# - avoid-redundant-async
|
||||
# - avoid-redundant-else
|
||||
# - avoid-unnecessary-nullable-return-type
|
||||
# - avoid-redundant-pragma-inline
|
||||
# - avoid-nested-records
|
||||
# - avoid-redundant-positional-field-name
|
||||
# - avoid-explicit-pattern-field-name
|
||||
# - prefer-simpler-patterns-null-check
|
||||
# - avoid-unnecessary-return
|
||||
# - avoid-duplicate-patterns
|
||||
# - avoid-keywords-in-wildcard-pattern
|
||||
# - avoid-unnecessary-futures
|
||||
# - avoid-unnecessary-reassignment
|
||||
# - avoid-unnecessary-call
|
||||
# - avoid-unnecessary-stateful-widgets
|
||||
# - prefer-dedicated-media-query-methods
|
||||
# - avoid-unnecessary-overrides-in-state
|
||||
# - move-variable-closer-to-its-usage
|
||||
# - avoid-nullable-parameters-with-default-values
|
||||
# - prefer-null-aware-spread
|
||||
# - avoid-inferrable-type-arguments
|
||||
# - avoid-unnecessary-super
|
||||
# - avoid-unnecessary-collections
|
||||
# - avoid-unnecessary-extends
|
||||
# - avoid-unnecessary-enum-arguments
|
||||
# - prefer-contains
|
||||
# Enable with the next release
|
||||
# - prefer-simpler-boolean-expressions
|
||||
# - prefer-spacing
|
||||
# - avoid-unnecessary-continue
|
||||
# - avoid-unnecessary-compare-to
|
||||
|
||||
# Style
|
||||
# - prefer-trailing-comma
|
||||
# - unnecessary-trailing-comma
|
||||
# - prefer-declaring-const-constructor
|
||||
# - prefer-single-widget-per-file
|
||||
# - prefer-prefixed-global-constants
|
||||
# - prefer-correct-callback-field-name
|
||||
|
1
mobile/dcm_global.yaml
Normal file
1
mobile/dcm_global.yaml
Normal file
@ -0,0 +1 @@
|
||||
version: '>=1.29.0 <1.30.0'
|
@ -1,8 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
List<ColorFilter> filters = [
|
||||
const List<ColorFilter> filters = [
|
||||
//Original
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
@ -25,7 +25,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Vintage
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.8,
|
||||
0.1,
|
||||
0.1,
|
||||
@ -48,7 +48,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Mood
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.2,
|
||||
0.1,
|
||||
0.1,
|
||||
@ -71,7 +71,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Crisp
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.2,
|
||||
0,
|
||||
0,
|
||||
@ -94,7 +94,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Cool
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.9,
|
||||
0,
|
||||
0.2,
|
||||
@ -117,7 +117,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Blush
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.1,
|
||||
0.1,
|
||||
0.1,
|
||||
@ -140,7 +140,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Sunkissed
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.3,
|
||||
0,
|
||||
0.1,
|
||||
@ -163,7 +163,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Fresh
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.2,
|
||||
0,
|
||||
0,
|
||||
@ -186,7 +186,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Classic
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.1,
|
||||
0,
|
||||
-0.1,
|
||||
@ -209,7 +209,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Lomo-ish
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.5,
|
||||
0,
|
||||
0.1,
|
||||
@ -232,7 +232,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Nashville
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.2,
|
||||
0.15,
|
||||
-0.15,
|
||||
@ -255,7 +255,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Valencia
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.15,
|
||||
0.1,
|
||||
0.1,
|
||||
@ -278,7 +278,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Clarendon
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.2,
|
||||
0,
|
||||
0,
|
||||
@ -301,7 +301,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Moon
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.33,
|
||||
0.33,
|
||||
0.33,
|
||||
@ -324,7 +324,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Willow
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.5,
|
||||
0.5,
|
||||
0.5,
|
||||
@ -347,7 +347,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Kodak
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.3,
|
||||
0.1,
|
||||
-0.1,
|
||||
@ -370,7 +370,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Frost
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.8,
|
||||
0.2,
|
||||
0.1,
|
||||
@ -393,7 +393,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Night Vision
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.1,
|
||||
0.95,
|
||||
0.2,
|
||||
@ -416,7 +416,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Sunset
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.5,
|
||||
0.2,
|
||||
0,
|
||||
@ -439,7 +439,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Noir
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.3,
|
||||
-0.3,
|
||||
0.1,
|
||||
@ -462,7 +462,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Dreamy
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.1,
|
||||
0.1,
|
||||
0.1,
|
||||
@ -485,7 +485,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Sepia
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.393,
|
||||
0.769,
|
||||
0.189,
|
||||
@ -508,7 +508,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Radium
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.438,
|
||||
-0.062,
|
||||
-0.062,
|
||||
@ -531,7 +531,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Aqua
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.2126,
|
||||
0.7152,
|
||||
0.0722,
|
||||
@ -554,7 +554,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Purple Haze
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.3,
|
||||
0,
|
||||
1.2,
|
||||
@ -577,7 +577,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Lemonade
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.2,
|
||||
0.1,
|
||||
0,
|
||||
@ -600,7 +600,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Caramel
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.6,
|
||||
0.2,
|
||||
0,
|
||||
@ -623,7 +623,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Peachy
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.3,
|
||||
0.5,
|
||||
0,
|
||||
@ -646,7 +646,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Neon
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
@ -669,7 +669,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Cold Morning
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.9,
|
||||
0.1,
|
||||
0.2,
|
||||
@ -692,7 +692,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Lush
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.9,
|
||||
0.2,
|
||||
0,
|
||||
@ -715,7 +715,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Urban Neon
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
1.1,
|
||||
0,
|
||||
0.3,
|
||||
@ -738,7 +738,7 @@ List<ColorFilter> filters = [
|
||||
0,
|
||||
]),
|
||||
//Monochrome
|
||||
const ColorFilter.matrix([
|
||||
ColorFilter.matrix([
|
||||
0.6,
|
||||
0.2,
|
||||
0.2,
|
||||
|
@ -229,7 +229,6 @@ class ImmichAppState extends ConsumerState<ImmichApp>
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: prefer-single-widget-per-file
|
||||
class MainWidget extends StatelessWidget {
|
||||
const MainWidget({super.key});
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:immich_mobile/entities/album.entity.dart';
|
||||
|
||||
class AvailableAlbum {
|
||||
@ -16,7 +14,6 @@ class AvailableAlbum {
|
||||
Album? album,
|
||||
int? assetCount,
|
||||
DateTime? lastBackup,
|
||||
Uint8List? thumbnailData,
|
||||
}) {
|
||||
return AvailableAlbum(
|
||||
album: album ?? this.album,
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore_for_file: add-copy-with
|
||||
|
||||
sealed class MapEvent {
|
||||
const MapEvent();
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
||||
});
|
||||
});
|
||||
|
||||
PhotoViewGalleryPageOptions buildImage(BuildContext context, Asset asset) {
|
||||
PhotoViewGalleryPageOptions buildImage(Asset asset) {
|
||||
return PhotoViewGalleryPageOptions(
|
||||
onDragStart: (_, details, __) {
|
||||
localPosition.value = details.localPosition;
|
||||
@ -312,7 +312,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
if (newAsset.isImage && !isPlayingMotionVideo) {
|
||||
return buildImage(context, newAsset);
|
||||
return buildImage(newAsset);
|
||||
}
|
||||
return buildVideo(context, newAsset);
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore_for_file: avoid-local-functions
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
@ -144,7 +142,6 @@ class _Feature {
|
||||
final Future<void> Function(BuildContext, WidgetRef _) onTap;
|
||||
}
|
||||
|
||||
// ignore: prefer-single-widget-per-file
|
||||
class _DevLogs extends StatelessWidget {
|
||||
const _DevLogs();
|
||||
|
||||
@ -172,7 +169,6 @@ class _DevLogs extends StatelessWidget {
|
||||
builder: (_, logMessages) {
|
||||
return ListView.separated(
|
||||
itemBuilder: (ctx, index) {
|
||||
// ignore: avoid-unsafe-collection-methods
|
||||
final logMessage = logMessages.data![index];
|
||||
return ListTile(
|
||||
title: Text(
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore_for_file: prefer-single-widget-per-file
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -5,4 +5,4 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'api.provider.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
ApiService apiService(Ref ref) => ApiService();
|
||||
ApiService apiService(Ref _) => ApiService();
|
||||
|
2
mobile/lib/providers/api.provider.g.dart
generated
2
mobile/lib/providers/api.provider.g.dart
generated
@ -6,7 +6,7 @@ part of 'api.provider.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$apiServiceHash() => r'93a7e3b4d3004741abc3061c4688239c3a72f9c4';
|
||||
String _$apiServiceHash() => r'187a7de59b064fab1104c23717f18ce0ae3e426c';
|
||||
|
||||
/// See also [apiService].
|
||||
@ProviderFor(apiService)
|
||||
|
@ -5,4 +5,4 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'app_settings.provider.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
AppSettingsService appSettingsService(Ref ref) => AppSettingsService();
|
||||
AppSettingsService appSettingsService(Ref _) => AppSettingsService();
|
||||
|
@ -7,7 +7,7 @@ part of 'app_settings.provider.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$appSettingsServiceHash() =>
|
||||
r'3736e0d384ec7b1f896938589656dd6eb1552d60';
|
||||
r'2aa16d76a8df869c39486325efc1d08b2d2c284c';
|
||||
|
||||
/// See also [appSettingsService].
|
||||
@ProviderFor(appSettingsService)
|
||||
|
@ -39,6 +39,6 @@ final assetStackStateProvider = StateNotifierProvider.autoDispose
|
||||
);
|
||||
|
||||
@riverpod
|
||||
int assetStackIndex(Ref ref, Asset asset) {
|
||||
int assetStackIndex(Ref _) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -6,155 +6,22 @@ part of 'asset_stack.provider.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$assetStackIndexHash() => r'38b4b0116e3e4592620b118ae01cf89b77da9cfe';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
String _$assetStackIndexHash() => r'086ddb782e3eb38b80d755666fe35be8fe7322d7';
|
||||
|
||||
/// See also [assetStackIndex].
|
||||
@ProviderFor(assetStackIndex)
|
||||
const assetStackIndexProvider = AssetStackIndexFamily();
|
||||
|
||||
/// See also [assetStackIndex].
|
||||
class AssetStackIndexFamily extends Family<int> {
|
||||
/// See also [assetStackIndex].
|
||||
const AssetStackIndexFamily();
|
||||
|
||||
/// See also [assetStackIndex].
|
||||
AssetStackIndexProvider call(
|
||||
Asset asset,
|
||||
) {
|
||||
return AssetStackIndexProvider(
|
||||
asset,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AssetStackIndexProvider getProviderOverride(
|
||||
covariant AssetStackIndexProvider provider,
|
||||
) {
|
||||
return call(
|
||||
provider.asset,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'assetStackIndexProvider';
|
||||
}
|
||||
|
||||
/// See also [assetStackIndex].
|
||||
class AssetStackIndexProvider extends AutoDisposeProvider<int> {
|
||||
/// See also [assetStackIndex].
|
||||
AssetStackIndexProvider(
|
||||
Asset asset,
|
||||
) : this._internal(
|
||||
(ref) => assetStackIndex(
|
||||
ref as AssetStackIndexRef,
|
||||
asset,
|
||||
),
|
||||
from: assetStackIndexProvider,
|
||||
final assetStackIndexProvider = AutoDisposeProvider<int>.internal(
|
||||
assetStackIndex,
|
||||
name: r'assetStackIndexProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$assetStackIndexHash,
|
||||
dependencies: AssetStackIndexFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
AssetStackIndexFamily._allTransitiveDependencies,
|
||||
asset: asset,
|
||||
);
|
||||
|
||||
AssetStackIndexProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.asset,
|
||||
}) : super.internal();
|
||||
|
||||
final Asset asset;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
int Function(AssetStackIndexRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: AssetStackIndexProvider._internal(
|
||||
(ref) => create(ref as AssetStackIndexRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
asset: asset,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeProviderElement<int> createElement() {
|
||||
return _AssetStackIndexProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is AssetStackIndexProvider && other.asset == asset;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, asset.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin AssetStackIndexRef on AutoDisposeProviderRef<int> {
|
||||
/// The parameter `asset` of this provider.
|
||||
Asset get asset;
|
||||
}
|
||||
|
||||
class _AssetStackIndexProviderElement extends AutoDisposeProviderElement<int>
|
||||
with AssetStackIndexRef {
|
||||
_AssetStackIndexProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
Asset get asset => (origin as AssetStackIndexProvider).asset;
|
||||
}
|
||||
typedef AssetStackIndexRef = AutoDisposeProviderRef<int>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
|
@ -144,7 +144,7 @@ class DownloadStateNotifier extends StateNotifier<DownloadState> {
|
||||
return await _downloadService.downloadAll(assets);
|
||||
}
|
||||
|
||||
void downloadAsset(Asset asset, BuildContext context) async {
|
||||
void downloadAsset(Asset asset) async {
|
||||
await _downloadService.download(asset);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'immich_logo_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<Uint8List> immichLogo(Ref ref) async {
|
||||
Future<Uint8List> immichLogo(Ref _) async {
|
||||
final json = await rootBundle.loadString('assets/immich-logo.json');
|
||||
final j = jsonDecode(json);
|
||||
return base64Decode(j['content']);
|
||||
|
2
mobile/lib/providers/immich_logo_provider.g.dart
generated
2
mobile/lib/providers/immich_logo_provider.g.dart
generated
@ -6,7 +6,7 @@ part of 'immich_logo_provider.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$immichLogoHash() => r'6f23d217c44279537b7edee1ca80ebf47f69a4d0';
|
||||
String _$immichLogoHash() => r'6de7fcca1ef9acef6ab7398eb0c664080747e0ea';
|
||||
|
||||
/// See also [immichLogo].
|
||||
@ProviderFor(immichLogo)
|
||||
|
@ -18,7 +18,6 @@ import 'package:immich_mobile/interfaces/backup_album.interface.dart';
|
||||
import 'package:immich_mobile/models/backup/backup_candidate.model.dart';
|
||||
import 'package:immich_mobile/models/backup/current_upload_asset.model.dart';
|
||||
import 'package:immich_mobile/models/backup/error_upload_asset.model.dart';
|
||||
import 'package:immich_mobile/models/backup/success_upload_asset.model.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
@ -489,7 +488,6 @@ class BackgroundService {
|
||||
_cancellationToken!,
|
||||
pmProgressHandler: pmProgressHandler,
|
||||
onSuccess: (result) => _onAssetUploaded(
|
||||
result: result,
|
||||
shouldNotify: notifyTotalProgress,
|
||||
),
|
||||
onProgress: (bytes, totalBytes) =>
|
||||
@ -511,7 +509,6 @@ class BackgroundService {
|
||||
}
|
||||
|
||||
void _onAssetUploaded({
|
||||
required SuccessUploadAsset result,
|
||||
bool shouldNotify = false,
|
||||
}) async {
|
||||
if (!shouldNotify) {
|
||||
|
@ -184,10 +184,10 @@ class BackupVerificationService {
|
||||
// for images: make sure they are pixel-wise identical
|
||||
// (skip first few KBs containing metadata)
|
||||
final Uint64List localImage =
|
||||
_fakeDecodeImg(local, await file.readAsBytes());
|
||||
_fakeDecodeImg(await file.readAsBytes());
|
||||
final res = await apiService.assetsApi
|
||||
.downloadAssetWithHttpInfo(remote.remoteId!);
|
||||
final Uint64List remoteImage = _fakeDecodeImg(remote, res.bodyBytes);
|
||||
final Uint64List remoteImage = _fakeDecodeImg(res.bodyBytes);
|
||||
|
||||
final eq = const ListEquality().equals(remoteImage, localImage);
|
||||
return eq;
|
||||
@ -198,7 +198,7 @@ class BackupVerificationService {
|
||||
return false;
|
||||
}
|
||||
|
||||
static Uint64List _fakeDecodeImg(Asset asset, Uint8List bytes) {
|
||||
static Uint64List _fakeDecodeImg(Uint8List bytes) {
|
||||
const headerLength = 131072; // assume header is at most 128 KB
|
||||
final start = bytes.length < headerLength * 2
|
||||
? (bytes.length ~/ (4 * 8)) * 8
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore_for_file: avoid-unsafe-collection-methods
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore_for_file: avoid-unsafe-collection-methods
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
@ -94,7 +94,7 @@ Future<void> handleFavoriteAssets(
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: toastMessage,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
gravity: toastGravity,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -164,9 +164,8 @@ Future<void> handleSetAssetsVisibility(
|
||||
WidgetRef ref,
|
||||
BuildContext context,
|
||||
AssetVisibilityEnum visibility,
|
||||
List<Asset> selection, {
|
||||
ToastGravity toastGravity = ToastGravity.BOTTOM,
|
||||
}) async {
|
||||
List<Asset> selection,
|
||||
) async {
|
||||
if (selection.isNotEmpty) {
|
||||
await ref
|
||||
.watch(assetProvider.notifier)
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
// Based on https://stackoverflow.com/a/52625182
|
||||
|
||||
import 'dart:async';
|
||||
@ -164,7 +163,6 @@ class _CustomLongPressGestureRecognizer extends LongPressGestureRecognizer {
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: prefer-single-widget-per-file
|
||||
class AssetIndexWrapper extends SingleChildRenderObjectWidget {
|
||||
final int rowIndex;
|
||||
final int sectionIndex;
|
||||
@ -177,6 +175,7 @@ class AssetIndexWrapper extends SingleChildRenderObjectWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
// ignore: library_private_types_in_public_api
|
||||
_AssetIndexProxy createRenderObject(BuildContext context) {
|
||||
return _AssetIndexProxy(
|
||||
index: AssetIndex(rowIndex: rowIndex, sectionIndex: sectionIndex),
|
||||
@ -186,6 +185,7 @@ class AssetIndexWrapper extends SingleChildRenderObjectWidget {
|
||||
@override
|
||||
void updateRenderObject(
|
||||
BuildContext context,
|
||||
// ignore: library_private_types_in_public_api
|
||||
_AssetIndexProxy renderObject,
|
||||
) {
|
||||
renderObject.index =
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore_for_file: prefer-single-widget-per-file
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
|
@ -80,8 +80,7 @@ class DraggableScrollbar extends StatefulWidget {
|
||||
this.labelTextBuilder,
|
||||
this.labelConstraints,
|
||||
}) : assert(child.scrollDirection == Axis.vertical),
|
||||
scrollThumbBuilder =
|
||||
_thumbRRectBuilder(scrollThumbKey, alwaysVisibleScrollThumb);
|
||||
scrollThumbBuilder = _thumbRRectBuilder(alwaysVisibleScrollThumb);
|
||||
|
||||
DraggableScrollbar.arrows({
|
||||
super.key,
|
||||
@ -97,8 +96,7 @@ class DraggableScrollbar extends StatefulWidget {
|
||||
this.labelTextBuilder,
|
||||
this.labelConstraints,
|
||||
}) : assert(child.scrollDirection == Axis.vertical),
|
||||
scrollThumbBuilder =
|
||||
_thumbArrowBuilder(scrollThumbKey, alwaysVisibleScrollThumb);
|
||||
scrollThumbBuilder = _thumbArrowBuilder(alwaysVisibleScrollThumb);
|
||||
|
||||
DraggableScrollbar.semicircle({
|
||||
super.key,
|
||||
@ -201,7 +199,6 @@ class DraggableScrollbar extends StatefulWidget {
|
||||
}
|
||||
|
||||
static ScrollThumbBuilder _thumbArrowBuilder(
|
||||
Key? scrollThumbKey,
|
||||
bool alwaysVisibleScrollThumb,
|
||||
) {
|
||||
return (
|
||||
@ -239,7 +236,6 @@ class DraggableScrollbar extends StatefulWidget {
|
||||
}
|
||||
|
||||
static ScrollThumbBuilder _thumbRRectBuilder(
|
||||
Key? scrollThumbKey,
|
||||
bool alwaysVisibleScrollThumb,
|
||||
) {
|
||||
return (
|
||||
|
@ -48,7 +48,7 @@ class ThumbnailImage extends ConsumerWidget {
|
||||
// Assets from response DTOs do not have an isar id, querying which would give us the default autoIncrement id
|
||||
final isFromDto = asset.id == noDbId;
|
||||
|
||||
Widget buildSelectionIcon(Asset asset) {
|
||||
Widget buildSelectionIcon() {
|
||||
if (isSelected) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
@ -233,7 +233,7 @@ class ThumbnailImage extends ConsumerWidget {
|
||||
padding: const EdgeInsets.all(3.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: buildSelectionIcon(asset),
|
||||
child: buildSelectionIcon(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -235,7 +235,6 @@ class BottomGalleryBar extends ConsumerWidget {
|
||||
|
||||
ref.read(downloadStateProvider.notifier).downloadAsset(
|
||||
asset,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ class GalleryAppBar extends ConsumerWidget {
|
||||
}
|
||||
|
||||
handleDownloadAsset() {
|
||||
ref.read(downloadStateProvider.notifier).downloadAsset(asset, context);
|
||||
ref.read(downloadStateProvider.notifier).downloadAsset(asset);
|
||||
}
|
||||
|
||||
handleLocateAsset() async {
|
||||
|
@ -13,7 +13,8 @@ OctoSet blurHashOrPlaceholder(
|
||||
}) {
|
||||
return OctoSet(
|
||||
placeholderBuilder: blurHashPlaceholderBuilder(blurhash, fit: fit),
|
||||
errorBuilder: blurHashErrorBuilder(blurhash, fit: fit),
|
||||
errorBuilder:
|
||||
blurHashErrorBuilder(blurhash, fit: fit, message: errorMessage),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,6 @@ mixin HitCornersDetector on PhotoViewControllerDelegate {
|
||||
bool _shouldMoveAxis(
|
||||
HitCorners hitCorners,
|
||||
double mainAxisMove,
|
||||
double crossAxisMove,
|
||||
) {
|
||||
if (mainAxisMove == 0) {
|
||||
return false;
|
||||
@ -47,17 +46,15 @@ mixin HitCornersDetector on PhotoViewControllerDelegate {
|
||||
bool _shouldMoveX(Offset move) {
|
||||
final hitCornersX = _hitCornersX();
|
||||
final mainAxisMove = move.dx;
|
||||
final crossAxisMove = move.dy;
|
||||
|
||||
return _shouldMoveAxis(hitCornersX, mainAxisMove, crossAxisMove);
|
||||
return _shouldMoveAxis(hitCornersX, mainAxisMove);
|
||||
}
|
||||
|
||||
bool _shouldMoveY(Offset move) {
|
||||
final hitCornersY = _hitCornersY();
|
||||
final mainAxisMove = move.dy;
|
||||
final crossAxisMove = move.dx;
|
||||
|
||||
return _shouldMoveAxis(hitCornersY, mainAxisMove, crossAxisMove);
|
||||
return _shouldMoveAxis(hitCornersY, mainAxisMove);
|
||||
}
|
||||
|
||||
bool shouldMove(Offset move, Axis mainAxis) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user