mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-26 01:10:39 +00:00
Compare commits
5 commits
eeb70bfaff
...
f49679353d
Author | SHA1 | Date | |
---|---|---|---|
|
f49679353d | ||
|
4aa71d944b | ||
|
f1d9d61cf0 | ||
|
b61a40fd04 | ||
|
b1722160d5 |
13 changed files with 63 additions and 30 deletions
9
.github/workflows/pr_check.yml
vendored
9
.github/workflows/pr_check.yml
vendored
|
@ -15,7 +15,7 @@ jobs:
|
||||||
analyze_and_test:
|
analyze_and_test:
|
||||||
name: Analyze & test
|
name: Analyze & test
|
||||||
runs-on: macos-11
|
runs-on: macos-11
|
||||||
timeout-minutes: 10
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
|
@ -47,3 +47,10 @@ jobs:
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: flutter test
|
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
2
.gitignore
vendored
|
@ -57,6 +57,6 @@ keystore.properties
|
||||||
android/app/google-services.json
|
android/app/google-services.json
|
||||||
ios/firebase_app_id_file.json
|
ios/firebase_app_id_file.json
|
||||||
ios/Runner/GoogleService-Info.plist
|
ios/Runner/GoogleService-Info.plist
|
||||||
lib/firebase_options.dart
|
/lib/firebase_options.dart
|
||||||
|
|
||||||
coverage/
|
coverage/
|
25
README.md
25
README.md
|
@ -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).
|
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
|
### 3. Project setup
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
As part of the app's functionallity is in the private repo, you have to replace these lines in _pubspec.yaml_:
|
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"
|
url: "https://github.com/vodemn/m3_lightmeter_iap"
|
||||||
ref: main
|
ref: main
|
||||||
```
|
```
|
||||||
|
|
||||||
with these:
|
with these:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
m3_lightmeter_iap:
|
m3_lightmeter_iap:
|
||||||
path: 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:
|
Then you can fetch all the neccessary dependencies and generate translation files by running the following commands:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
flutter pub get
|
flutter pub get
|
||||||
flutter pub run intl_utils:generate
|
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
|
#### Android
|
||||||
|
|
||||||
You can build an apk by running the following command from the root of the repository:
|
You can build an apk by running the following command from the root of the repository:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
flutter build apk --release --flavor dev --dart-define cameraPreviewAspectRatio=240/320 -t lib/main_dev.dart
|
flutter build apk --release --flavor dev --dart-define cameraPreviewAspectRatio=240/320 -t lib/main_dev.dart
|
||||||
```
|
```
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'package:m3_lightmeter_iap/src/providers/iap_products_provider.dart';
|
||||||
export 'src/data/models/iap_product.dart';
|
export 'src/data/models/iap_product.dart';
|
||||||
|
|
||||||
export 'src/providers/equipment_profile_provider.dart';
|
export 'src/providers/equipment_profile_provider.dart';
|
||||||
|
export 'src/providers/films_provider.dart';
|
||||||
export 'src/providers/iap_products_provider.dart';
|
export 'src/providers/iap_products_provider.dart';
|
||||||
|
|
||||||
class IAPProviders extends StatelessWidget {
|
class IAPProviders extends StatelessWidget {
|
||||||
|
|
|
@ -23,6 +23,7 @@ class FilmsProviderState extends State<FilmsProvider> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Films(
|
return Films(
|
||||||
values: const [Film.other()],
|
values: const [Film.other()],
|
||||||
|
filmsInUse: const [Film.other()],
|
||||||
selected: const Film.other(),
|
selected: const Film.other(),
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
);
|
);
|
||||||
|
@ -34,15 +35,28 @@ class FilmsProviderState extends State<FilmsProvider> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Films extends SelectableInheritedModel<Film> {
|
class Films extends SelectableInheritedModel<Film> {
|
||||||
|
final List<Film> filmsInUse;
|
||||||
|
|
||||||
const Films({
|
const Films({
|
||||||
super.key,
|
super.key,
|
||||||
required super.values,
|
required super.values,
|
||||||
|
required this.filmsInUse,
|
||||||
required super.selected,
|
required super.selected,
|
||||||
required super.child,
|
required super.child,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// [Film.other()] + all the custom fields with actual reciprocity formulas
|
||||||
static List<Film> of(BuildContext context) {
|
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) {
|
static Film selectedOf(BuildContext context) {
|
||||||
|
|
|
@ -13,22 +13,6 @@ class SelectableInheritedModel<T> extends InheritedModel<SelectableAspect> {
|
||||||
final List<T> values;
|
final List<T> values;
|
||||||
final T selected;
|
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
|
@override
|
||||||
bool updateShouldNotify(SelectableInheritedModel oldWidget) => true;
|
bool updateShouldNotify(SelectableInheritedModel oldWidget) => true;
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
"film": "Film",
|
"film": "Film",
|
||||||
"filmPush": "Film (push)",
|
"filmPush": "Film (push)",
|
||||||
"filmPull": "Film (pull)",
|
"filmPull": "Film (pull)",
|
||||||
|
"filmReciprocityHint": "Applies correction for shutter speeds grater than 1 second",
|
||||||
"equipment": "Equipment",
|
"equipment": "Equipment",
|
||||||
"equipmentProfileName": "Equipment profile name",
|
"equipmentProfileName": "Equipment profile name",
|
||||||
"equipmentProfileNameHint": "Praktica MTL5B",
|
"equipmentProfileNameHint": "Praktica MTL5B",
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
"film": "Pellicule",
|
"film": "Pellicule",
|
||||||
"filmPush": "Pellicule (push)",
|
"filmPush": "Pellicule (push)",
|
||||||
"filmPull": "Pellicule (pull)",
|
"filmPull": "Pellicule (pull)",
|
||||||
|
"filmReciprocityHint": "La correction s'applique aux vitesses d'obturation supérieures à 1 seconde",
|
||||||
"equipment": "Équipement",
|
"equipment": "Équipement",
|
||||||
"equipmentProfileName": "Nom du profil de l'équipement",
|
"equipmentProfileName": "Nom du profil de l'équipement",
|
||||||
"equipmentProfileNameHint": "Praktica MTL5B",
|
"equipmentProfileNameHint": "Praktica MTL5B",
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
"film": "Пленка",
|
"film": "Пленка",
|
||||||
"filmPush": "Пленка (push)",
|
"filmPush": "Пленка (push)",
|
||||||
"filmPull": "Пленка (pull)",
|
"filmPull": "Пленка (pull)",
|
||||||
|
"filmReciprocityHint": "Применяет коррекцию для выдержек длиннее 1 секунды",
|
||||||
"equipment": "Оборудование",
|
"equipment": "Оборудование",
|
||||||
"equipmentProfileName": "Название профиля",
|
"equipmentProfileName": "Название профиля",
|
||||||
"equipmentProfileNameHint": "Praktica MTL5B",
|
"equipmentProfileNameHint": "Praktica MTL5B",
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
"film": "胶片",
|
"film": "胶片",
|
||||||
"filmPush": "胶片 (push)",
|
"filmPush": "胶片 (push)",
|
||||||
"filmPull": "胶片 (pull)",
|
"filmPull": "胶片 (pull)",
|
||||||
|
"filmReciprocityHint": "Applies correction for shutter speeds grater than 1 second",
|
||||||
"equipment": "设备",
|
"equipment": "设备",
|
||||||
"equipmentProfileName": "设备配置名称",
|
"equipmentProfileName": "设备配置名称",
|
||||||
"equipmentProfileNameHint": "Praktica MTL5B",
|
"equipmentProfileNameHint": "Praktica MTL5B",
|
||||||
|
|
|
@ -15,8 +15,9 @@ class FilmPicker extends StatelessWidget {
|
||||||
return AnimatedDialogPicker<Film>(
|
return AnimatedDialogPicker<Film>(
|
||||||
icon: Icons.camera_roll,
|
icon: Icons.camera_roll,
|
||||||
title: S.of(context).film,
|
title: S.of(context).film,
|
||||||
|
subtitle: S.of(context).filmReciprocityHint,
|
||||||
selectedValue: Films.selectedOf(context),
|
selectedValue: Films.selectedOf(context),
|
||||||
values: Films.of(context),
|
values: Films.inUseOf(context),
|
||||||
itemTitleBuilder: (_, value) => Text(value.name.isEmpty ? S.of(context).none : value.name),
|
itemTitleBuilder: (_, value) => Text(value.name.isEmpty ? S.of(context).none : value.name),
|
||||||
onChanged: FilmsProvider.of(context).setFilm,
|
onChanged: FilmsProvider.of(context).setFilm,
|
||||||
closedChild: ReadingValueContainer.singleValue(
|
closedChild: ReadingValueContainer.singleValue(
|
||||||
|
|
|
@ -20,8 +20,8 @@ class FilmsListTile extends StatelessWidget {
|
||||||
icon: const Icon(Icons.camera_roll),
|
icon: const Icon(Icons.camera_roll),
|
||||||
title: S.of(context).filmsInUse,
|
title: S.of(context).filmsInUse,
|
||||||
description: S.of(context).filmsInUseDescription,
|
description: S.of(context).filmsInUseDescription,
|
||||||
values: Film.values.sublist(1),
|
values: Films.of(context).sublist(1),
|
||||||
selectedValues: Films.of(context),
|
selectedValues: Films.inUseOf(context),
|
||||||
titleAdapter: (_, value) => value.name,
|
titleAdapter: (_, value) => value.name,
|
||||||
),
|
),
|
||||||
).then((values) {
|
).then((values) {
|
||||||
|
|
11
m3_lightmeter.code-workspace
Normal file
11
m3_lightmeter.code-workspace
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "iap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"settings": {}
|
||||||
|
}
|
Loading…
Reference in a new issue