Compare commits

...

5 commits

Author SHA1 Message Date
Vadim
f49679353d Update .gitignore 2023-09-14 16:46:24 +02:00
Vadim
4aa71d944b added workspace file 2023-09-14 16:38:55 +02:00
Vadim
f1d9d61cf0 added reciprocity description 2023-09-14 16:30:37 +02:00
Vadim
b61a40fd04 sync iap stub with iap changes 2023-09-14 15:58:28 +02:00
Vadim
b1722160d5 sync with iap changes 2023-09-14 15:38:28 +02:00
13 changed files with 63 additions and 30 deletions

View file

@ -15,7 +15,7 @@ jobs:
analyze_and_test:
name: Analyze & test
runs-on: macos-11
timeout-minutes: 10
timeout-minutes: 5
steps:
- uses: actions/checkout@v3
with:
@ -47,3 +47,10 @@ jobs:
- name: Run tests
run: flutter test
- name: Analyze project source with stub
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
run: |
bash ./.github/scripts/stub_iap.sh
flutter pub get
flutter analyze lib --fatal-infos

2
.gitignore vendored
View file

@ -57,6 +57,6 @@ keystore.properties
android/app/google-services.json
ios/firebase_app_id_file.json
ios/Runner/GoogleService-Info.plist
lib/firebase_options.dart
/lib/firebase_options.dart
coverage/

View file

@ -33,11 +33,7 @@ Without further delay behold my new Lightmeter app inspired by Material You (a.k
To build this app you need to install Flutter 3.10.0 stable. [How to install](https://docs.flutter.dev/get-started/install).
### 2. (Optional) Install Firebase
Out of the box Firebase Crashlytics won't work. If you want to add Crashlytics to your local build please follow [this guide](https://firebase.google.com/docs/flutter/setup).
### 3. Get packages
### 3. Project setup
As part of the app's functionallity is in the private repo, you have to replace these lines in _pubspec.yaml_:
@ -47,24 +43,39 @@ m3_lightmeter_iap:
url: "https://github.com/vodemn/m3_lightmeter_iap"
ref: main
```
with these:
```yaml
m3_lightmeter_iap:
path: iap
```
and run `flutter pub get` from the _iap/_ folder.
You can do it simply by running the script:
```console
sh .github/scripts/stub_iap.sh
```
> If you are using VSCode, you can open the workspace like so: _File -> Open Workspace from File -> m3_lightmeter.code-workspace_. Otherwise you have to run `flutter pub get` command from the iap folder.
Then you can fetch all the neccessary dependencies and generate translation files by running the following commands:
```console
flutter pub get
flutter pub run intl_utils:generate
```
### 4. Build
### 4. (Optional) Install Firebase
Out of the box Firebase Crashlytics won't work. If you want to add Crashlytics to your local build please follow [this guide](https://firebase.google.com/docs/flutter/setup).
### 5. Build
#### Android
You can build an apk by running the following command from the root of the repository:
```console
flutter build apk --release --flavor dev --dart-define cameraPreviewAspectRatio=240/320 -t lib/main_dev.dart
```

View file

@ -8,6 +8,7 @@ import 'package:m3_lightmeter_iap/src/providers/iap_products_provider.dart';
export 'src/data/models/iap_product.dart';
export 'src/providers/equipment_profile_provider.dart';
export 'src/providers/films_provider.dart';
export 'src/providers/iap_products_provider.dart';
class IAPProviders extends StatelessWidget {

View file

@ -23,6 +23,7 @@ class FilmsProviderState extends State<FilmsProvider> {
Widget build(BuildContext context) {
return Films(
values: const [Film.other()],
filmsInUse: const [Film.other()],
selected: const Film.other(),
child: widget.child,
);
@ -34,15 +35,28 @@ class FilmsProviderState extends State<FilmsProvider> {
}
class Films extends SelectableInheritedModel<Film> {
final List<Film> filmsInUse;
const Films({
super.key,
required super.values,
required this.filmsInUse,
required super.selected,
required super.child,
});
/// [Film.other()] + all the custom fields with actual reciprocity formulas
static List<Film> of(BuildContext context) {
return InheritedModel.inheritFrom<Films>(context, aspect: SelectableAspect.list)!.values;
return InheritedModel.inheritFrom<Films>(context)!.values;
}
/// [Film.other()] + films in use selected by user
static List<Film> inUseOf<T>(BuildContext context) {
return InheritedModel.inheritFrom<Films>(
context,
aspect: SelectableAspect.list,
)!
.filmsInUse;
}
static Film selectedOf(BuildContext context) {

View file

@ -13,22 +13,6 @@ class SelectableInheritedModel<T> extends InheritedModel<SelectableAspect> {
final List<T> values;
final T selected;
static List<T> of<T>(BuildContext context) {
return InheritedModel.inheritFrom<SelectableInheritedModel<T>>(
context,
aspect: SelectableAspect.list,
)!
.values;
}
static T selectedOf<T>(BuildContext context) {
return InheritedModel.inheritFrom<SelectableInheritedModel>(
context,
aspect: SelectableAspect.selected,
)!
.selected;
}
@override
bool updateShouldNotify(SelectableInheritedModel oldWidget) => true;

View file

@ -43,6 +43,7 @@
"film": "Film",
"filmPush": "Film (push)",
"filmPull": "Film (pull)",
"filmReciprocityHint": "Applies correction for shutter speeds grater than 1 second",
"equipment": "Equipment",
"equipmentProfileName": "Equipment profile name",
"equipmentProfileNameHint": "Praktica MTL5B",

View file

@ -43,6 +43,7 @@
"film": "Pellicule",
"filmPush": "Pellicule (push)",
"filmPull": "Pellicule (pull)",
"filmReciprocityHint": "La correction s'applique aux vitesses d'obturation supérieures à 1 seconde",
"equipment": "Équipement",
"equipmentProfileName": "Nom du profil de l'équipement",
"equipmentProfileNameHint": "Praktica MTL5B",

View file

@ -43,6 +43,7 @@
"film": "Пленка",
"filmPush": "Пленка (push)",
"filmPull": "Пленка (pull)",
"filmReciprocityHint": "Применяет коррекцию для выдержек длиннее 1 секунды",
"equipment": "Оборудование",
"equipmentProfileName": "Название профиля",
"equipmentProfileNameHint": "Praktica MTL5B",
@ -92,4 +93,4 @@
}
}
}
}
}

View file

@ -43,6 +43,7 @@
"film": "胶片",
"filmPush": "胶片 (push)",
"filmPull": "胶片 (pull)",
"filmReciprocityHint": "Applies correction for shutter speeds grater than 1 second",
"equipment": "设备",
"equipmentProfileName": "设备配置名称",
"equipmentProfileNameHint": "Praktica MTL5B",

View file

@ -15,8 +15,9 @@ class FilmPicker extends StatelessWidget {
return AnimatedDialogPicker<Film>(
icon: Icons.camera_roll,
title: S.of(context).film,
subtitle: S.of(context).filmReciprocityHint,
selectedValue: Films.selectedOf(context),
values: Films.of(context),
values: Films.inUseOf(context),
itemTitleBuilder: (_, value) => Text(value.name.isEmpty ? S.of(context).none : value.name),
onChanged: FilmsProvider.of(context).setFilm,
closedChild: ReadingValueContainer.singleValue(

View file

@ -20,8 +20,8 @@ class FilmsListTile extends StatelessWidget {
icon: const Icon(Icons.camera_roll),
title: S.of(context).filmsInUse,
description: S.of(context).filmsInUseDescription,
values: Film.values.sublist(1),
selectedValues: Films.of(context),
values: Films.of(context).sublist(1),
selectedValues: Films.inUseOf(context),
titleAdapter: (_, value) => value.name,
),
).then((values) {

View file

@ -0,0 +1,11 @@
{
"folders": [
{
"path": "iap"
},
{
"path": "."
}
],
"settings": {}
}