mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-21 15:00:40 +00:00
Show release notes after update (#178)
* replace generated release notes with pre-built assets * implemented release notes dialog * store release notes for version * show release notes dialog after update * added release notes dialog to settings * allow blank values in settings * updated release notes
This commit is contained in:
parent
f62f658be8
commit
881778b313
11 changed files with 174 additions and 44 deletions
40
.github/workflows/create_release.yml
vendored
40
.github/workflows/create_release.yml
vendored
|
@ -18,10 +18,6 @@ on:
|
||||||
description: "Version"
|
description: "Version"
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
release-notes:
|
|
||||||
description: "Release notes"
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
run-integration-tests:
|
run-integration-tests:
|
||||||
description: "Run integration tests"
|
description: "Run integration tests"
|
||||||
required: true
|
required: true
|
||||||
|
@ -60,25 +56,9 @@ jobs:
|
||||||
stage-backend: false
|
stage-backend: false
|
||||||
version: ${{ inputs.version }}
|
version: ${{ inputs.version }}
|
||||||
|
|
||||||
generate-release-notes:
|
|
||||||
name: Generate release notes
|
|
||||||
needs: [build-android, build-ios]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Generate release notes
|
|
||||||
run: |
|
|
||||||
echo ${{ inputs.release-notes }} > whatsnew-en-US.md
|
|
||||||
perl -i -pe 's/\s{1}(-{1})/\n$1/g' whatsnew-en-US.md
|
|
||||||
|
|
||||||
- name: Upload merged_native_libs.zip to artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: whatsnew-en-US
|
|
||||||
path: whatsnew-en-US.md
|
|
||||||
|
|
||||||
create-github-release:
|
create-github-release:
|
||||||
name: Create Github release
|
name: Create Github release
|
||||||
needs: [generate-release-notes]
|
needs: [build-android, build-ios]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
@ -112,21 +92,16 @@ jobs:
|
||||||
- name: Rename apk
|
- name: Rename apk
|
||||||
run: mv app-prod-release.apk m3_lightmeter.apk
|
run: mv app-prod-release.apk m3_lightmeter.apk
|
||||||
|
|
||||||
- name: Download release notes
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: whatsnew-en-US
|
|
||||||
|
|
||||||
- uses: ncipollo/release-action@v1.12.0
|
- uses: ncipollo/release-action@v1.12.0
|
||||||
with:
|
with:
|
||||||
artifacts: "m3_lightmeter.apk"
|
artifacts: "m3_lightmeter.apk"
|
||||||
skipIfReleaseExists: true
|
skipIfReleaseExists: true
|
||||||
tag: "v${{ github.event.inputs.version }}"
|
tag: "v${{ github.event.inputs.version }}"
|
||||||
bodyFile: "whatsnew-en-US.md"
|
bodyFile: "assets/release_notes/release_notes_en_${{ inputs.version }}.md"
|
||||||
|
|
||||||
create-google-play-release:
|
create-google-play-release:
|
||||||
name: Create Google Play release
|
name: Create Google Play release
|
||||||
needs: [generate-release-notes]
|
needs: [build-android, build-ios]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
@ -143,14 +118,9 @@ jobs:
|
||||||
unzip app-prod-release.aab
|
unzip app-prod-release.aab
|
||||||
(cd base/lib && zip -r "$OLDPWD/merged_native_libs.zip" .)
|
(cd base/lib && zip -r "$OLDPWD/merged_native_libs.zip" .)
|
||||||
|
|
||||||
- name: Download release notes
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: whatsnew-en-US
|
|
||||||
|
|
||||||
- name: Move release notes to a folder
|
- name: Move release notes to a folder
|
||||||
run: |
|
run: |
|
||||||
mv whatsnew-en-US.md whatsnew-en-US
|
mv assets/release_notes/release_notes_en_${{ inputs.version }}.md whatsnew-en-US
|
||||||
mkdir whatsnew
|
mkdir whatsnew
|
||||||
mv whatsnew-en-US whatsnew
|
mv whatsnew-en-US whatsnew
|
||||||
|
|
||||||
|
@ -177,7 +147,7 @@ jobs:
|
||||||
|
|
||||||
upload-to-app-store:
|
upload-to-app-store:
|
||||||
name: Upload to App Store
|
name: Upload to App Store
|
||||||
needs: [generate-release-notes]
|
needs: [build-android, build-ios]
|
||||||
runs-on: macos-13
|
runs-on: macos-13
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
4
assets/release_notes/release_notes_en_0.19.0.md
Normal file
4
assets/release_notes/release_notes_en_0.19.0.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
- [Pro] Added a timer for shooting long exposures without leaving the app, just tap the necessary shutter speed in the list.
|
||||||
|
- Long exposure values are no longer limited by 1" and are generated to match the list of aperture values.
|
||||||
|
- Refined the app's color palette & unified icons across the app.
|
||||||
|
- Added release notes dialog.
|
4
assets/release_notes/release_notes_ru_0.19.0.md
Normal file
4
assets/release_notes/release_notes_ru_0.19.0.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
- [Pro] Добавлен таймер для удобства съёмки при длительных выдержках. Достаточно просто нажать на нужное значение в списке экспозиционных пар.
|
||||||
|
- Длинные выдержки больше не ограничены 1" и генерируются в соответствии со значениями диафрагмы.
|
||||||
|
- Переработана цветовая палитра приложения и унифицированы иконки.
|
||||||
|
- Добавлен список изменений.
|
|
@ -32,6 +32,8 @@ class UserPreferencesService {
|
||||||
static const primaryColorKey = "primaryColor";
|
static const primaryColorKey = "primaryColor";
|
||||||
static const dynamicColorKey = "dynamicColor";
|
static const dynamicColorKey = "dynamicColor";
|
||||||
|
|
||||||
|
static const seenChangelogVersionKey = "seenChangelogVersion";
|
||||||
|
|
||||||
final SharedPreferences _sharedPreferences;
|
final SharedPreferences _sharedPreferences;
|
||||||
|
|
||||||
UserPreferencesService(this._sharedPreferences) {
|
UserPreferencesService(this._sharedPreferences) {
|
||||||
|
@ -157,4 +159,7 @@ class UserPreferencesService {
|
||||||
|
|
||||||
bool get dynamicColor => _sharedPreferences.getBool(dynamicColorKey) ?? false;
|
bool get dynamicColor => _sharedPreferences.getBool(dynamicColorKey) ?? false;
|
||||||
set dynamicColor(bool value) => _sharedPreferences.setBool(dynamicColorKey, value);
|
set dynamicColor(bool value) => _sharedPreferences.setBool(dynamicColorKey, value);
|
||||||
|
|
||||||
|
String get seenChangelogVersion => _sharedPreferences.getString(seenChangelogVersionKey) ?? '';
|
||||||
|
set seenChangelogVersion(String value) => _sharedPreferences.setString(seenChangelogVersionKey, value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,5 +119,15 @@
|
||||||
"tooltipUseLightSensor": "Use lightsensor",
|
"tooltipUseLightSensor": "Use lightsensor",
|
||||||
"tooltipUseCamera": "Use camera",
|
"tooltipUseCamera": "Use camera",
|
||||||
"tooltipOpenSettings": "Open settings",
|
"tooltipOpenSettings": "Open settings",
|
||||||
"exposurePair": "Exposure pair"
|
"exposurePair": "Exposure pair",
|
||||||
|
"whatsnew": "What's new?",
|
||||||
|
"changesInVersion": "Changes in version {version}:",
|
||||||
|
"@changesInVersion": {
|
||||||
|
"placeholders": {
|
||||||
|
"version": {
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"close": "Close"
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:lightmeter/generated/l10n.dart';
|
import 'package:lightmeter/generated/l10n.dart';
|
||||||
|
import 'package:lightmeter/screens/shared/release_notes_dialog/widget_dialog_release_notes.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
class VersionListTile extends StatelessWidget {
|
class VersionListTile extends StatelessWidget {
|
||||||
|
@ -7,14 +8,18 @@ class VersionListTile extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListTile(
|
return FutureBuilder<PackageInfo>(
|
||||||
leading: const Icon(Icons.info_outline),
|
future: PackageInfo.fromPlatform(),
|
||||||
title: Text(S.of(context).version),
|
builder: (context, snapshot) => ListTile(
|
||||||
trailing: FutureBuilder<PackageInfo>(
|
leading: const Icon(Icons.info_outline),
|
||||||
future: PackageInfo.fromPlatform(),
|
title: Text(S.of(context).version),
|
||||||
builder: (context, snapshot) => snapshot.data != null
|
onTap: snapshot.data != null
|
||||||
? Text(S.of(context).versionNumber(snapshot.data!.version, snapshot.data!.buildNumber))
|
? () => showDialog(
|
||||||
: const SizedBox.shrink(),
|
context: context,
|
||||||
|
builder: (_) => ReleaseNotesDialog(version: snapshot.data!.version),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
trailing: Text(S.of(context).versionNumber(snapshot.data?.version ?? '', snapshot.data?.buildNumber ?? '')),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:lightmeter/data/shared_prefs_service.dart';
|
||||||
|
import 'package:lightmeter/screens/shared/release_notes_dialog/state_release_notes.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
|
class ReleaseNotesBloc extends Cubit<ReleaseNotesState> {
|
||||||
|
final UserPreferencesService _userPreferencesService;
|
||||||
|
|
||||||
|
ReleaseNotesBloc(this._userPreferencesService) : super(const HiddenReleaseNotesDialogState()) {
|
||||||
|
_showDialogIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _showDialogIfNeeded() async {
|
||||||
|
PackageInfo.fromPlatform().then((value) {
|
||||||
|
emit(ShowReleaseNotesDialogState(value.version));
|
||||||
|
if (value.version != _userPreferencesService.seenChangelogVersion) {
|
||||||
|
emit(ShowReleaseNotesDialogState(value.version));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void setChangelogVersion() {
|
||||||
|
_userPreferencesService.seenChangelogVersion = (state as ShowReleaseNotesDialogState).version;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:lightmeter/providers/services_provider.dart';
|
||||||
|
import 'package:lightmeter/screens/shared/release_notes_dialog/bloc_release_notes.dart';
|
||||||
|
import 'package:lightmeter/screens/shared/release_notes_dialog/state_release_notes.dart';
|
||||||
|
import 'package:lightmeter/screens/shared/release_notes_dialog/widget_dialog_release_notes.dart';
|
||||||
|
|
||||||
|
class ReleaseNotesFlow extends StatelessWidget {
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const ReleaseNotesFlow({required this.child, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => ReleaseNotesBloc(ServicesProvider.of(context).userPreferencesService),
|
||||||
|
child: BlocListener<ReleaseNotesBloc, ReleaseNotesState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state is ShowReleaseNotesDialogState) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => ReleaseNotesDialog(version: state.version),
|
||||||
|
).then((_) => context.read<ReleaseNotesBloc>().setChangelogVersion());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
sealed class ReleaseNotesState {
|
||||||
|
const ReleaseNotesState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class HiddenReleaseNotesDialogState extends ReleaseNotesState {
|
||||||
|
const HiddenReleaseNotesDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowReleaseNotesDialogState extends ReleaseNotesState {
|
||||||
|
final String version;
|
||||||
|
|
||||||
|
const ShowReleaseNotesDialogState(this.version);
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart' show rootBundle;
|
||||||
|
import 'package:lightmeter/data/models/supported_locale.dart';
|
||||||
|
import 'package:lightmeter/generated/l10n.dart';
|
||||||
|
import 'package:lightmeter/providers/user_preferences_provider.dart';
|
||||||
|
import 'package:lightmeter/res/dimens.dart';
|
||||||
|
|
||||||
|
class ReleaseNotesDialog extends StatelessWidget {
|
||||||
|
final String version;
|
||||||
|
|
||||||
|
const ReleaseNotesDialog({required this.version, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text(S.of(context).whatsnew),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
S.of(context).changesInVersion(version),
|
||||||
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
|
),
|
||||||
|
const SizedBox(height: Dimens.grid8),
|
||||||
|
FutureBuilder<String>(
|
||||||
|
future: loadReleaseNotes(context),
|
||||||
|
builder: (context, snapshot) => Text(snapshot.data ?? ''),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: Navigator.of(context).pop,
|
||||||
|
child: Text(S.of(context).close),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> loadReleaseNotes(BuildContext context) async {
|
||||||
|
late final String localeName;
|
||||||
|
|
||||||
|
switch (UserPreferencesProvider.localeOf(context)) {
|
||||||
|
case SupportedLocale.ru:
|
||||||
|
localeName = SupportedLocale.ru.name;
|
||||||
|
default:
|
||||||
|
localeName = SupportedLocale.en.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return rootBundle.loadString('assets/release_notes/release_notes_${localeName}_$version.md');
|
||||||
|
} catch (e) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,6 +68,7 @@ flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
assets:
|
assets:
|
||||||
- assets/camera_stub_image.jpg
|
- assets/camera_stub_image.jpg
|
||||||
|
- assets/release_notes/
|
||||||
|
|
||||||
flutter_intl:
|
flutter_intl:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
Loading…
Reference in a new issue