Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App stores #383

Merged
merged 16 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
runs-on: macos-latest
strategy:
matrix:
flutter-version: ['3.13.1']
flutter-version: ['3.16.0', '3.19.1']

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/platforms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
runs-on-name: ['windows-latest']
flutter-version: ['3.3.12']
flutter-version: ['3.16.0']

runs-on: ${{ matrix.runs-on-name }}

Expand Down
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
## 10.0.0

This major update changes the structure of how the internal state is maintained and how access to app stores is provided. The API has not changed for the standard use cases. However, the way in which Appcast is used has changed slightly.

This update also makes it easier to extend upgrader to support more app stores without changing upgrader. This will come into play when used on Linux and Windows, or when supporting alternate app stores on Android.

## 10.0.0-alpha.3

- Fixed deprecation warning for WillPopScope and replaced it with PopScope, which required the minimum Flutter SDK version to be moved up to 3.16.0 in this package.
- Renamed parameter canDismissDialog to barrierDismissible in `UpgradeAlert`.

### 10.0.0

This major update changes the structure of how the internal state is maintained and how access to app stores is provided. The API has not changed for the standard use cases. However, the way in which Appcast is used has changed slightly.

This update also makes it easier to extend upgrader to support more app stores without changing upgrader. This will come into play when used on Linux and Windows, or when supporting alternate app stores on Android.

### Changes in 10.0.0
- Implemented [UpgraderState] that is used internally to replace evaluation ready.
- BREAKING: Removed Appcast configuration so that an Appcast [UpgraderStore] can be used.
- Fixed deprecation warning for WillPopScope and replaced it with PopScope, which required the minimum Flutter SDK version to be moved up to 3.16.0 in this package.
- Renamed parameter canDismissDialog to barrierDismissible in `UpgradeAlert`.

## 10.0.0-alpha.2

(README file and documentation updates)

This major update changes the structure of how the internal state is maintained and how access to app stores is provided. The API has not changed for the standard use cases. However, the way in which Appcast is used has changed slightly.

This update also makes it easier to extend upgrader to support more app stores without changing upgrader. This will come into play when used on Linux and Windows, or when supporting alternate app stores on Android.

### Changes in 10.0.0
- Implemented [UpgraderState] that is used internally to replace evaluation ready.
- BREAKING: Removed Appcast configuration so that an Appcast [UpgraderStore] can be used.

## 10.0.0-alpha.1

- Implemented [UpgraderState] that is used internally to replace evaluation ready.
- BREAKING: Removed Appcast configuration so that an Appcast [UpgraderStore] can be used.

## 9.0.0

### BREAKING CHANGES
Expand Down
103 changes: 68 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Tapping the UPDATE NOW button takes the user to the App Store (iOS) or Google Pl
Just wrap your home widget in the `UpgradeAlert` widget, and it will handle the rest.
```dart
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
const MyApp({super.key});

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -121,13 +121,13 @@ The card can be customized by changing the `CardTheme` on the `MaterialApp`, or

Here are the custom parameters for `UpgradeAlert`:

* canDismissDialog: can alert dialog be dismissed on tap outside of the alert dialog, which defaults to ```false``` (not used by UpgradeCard)
* barrierDismissible: used to indicate whether tapping on the barrier will dismiss the dialog, which defaults to ```false```
* cupertinoButtonTextStyle: the text style for the cupertino dialog buttons, which defaults to ```null```
* dialogStyle: the upgrade dialog style, either ```material``` or ```cupertino```, defaults to ```material```, used only by UpgradeAlert, works on Android and iOS.
* onIgnore: called when the ignore button is tapped, defaults to ```null```
* onLater: called when the later button is tapped, defaults to ```null```
* onUpdate: called when the update button is tapped, defaults to ```null```
* shouldPopScope: called when the back button is tapped, defaults to ```null```
* shouldPopScope: called to determine if the dialog blocks the current route from being popped, which defaults to ```null```
* showIgnore: hide or show Ignore button, which defaults to ```true```
* showLater: hide or show Later button, which defaults to ```true```
* showReleaseNotes: hide or show release notes, which defaults to ```true```
Expand All @@ -146,21 +146,45 @@ Here are the custom parameters for `UpgradeCard`:

The `Upgrader` class can be customized by setting parameters in the constructor, and passing it

* appcast: Provide an Appcast that can be replaced for mock testing, defaults to ```null```
* appcastConfig: the appcast configuration, defaults to ```null```
* client: an HTTP Client that can be replaced for mock testing, defaults to ```null```
* client: an HTTP Client that can be replaced for mock testing, defaults to `http.Client()`.
* countryCode: the country code that will override the system locale, which defaults to ```null```
* languageCode: the language code that will override the system locale, which defaults to ```null```
* debugDisplayAlways: always force the upgrade to be available, defaults to ```false```
* debugDisplayOnce: display the upgrade at least once, defaults to ```false```
* debugLogging: display logging statements, which defaults to ```false```
* durationUntilAlertAgain: duration until alerting user again, which defaults to ```3 days```
* languageCode: the language code that will override the system locale, which defaults to ```null```
* messages: optional localized messages used for display in `upgrader`
* minAppVersion: the minimum app version supported by this app. Earlier versions of this app will be forced to update to the current version. It should be a valid version string like this: ```2.0.13```. Defaults to ```null```.
* upgraderOS: Provides information on which OS this code is running on, defaults to ```null```
* minAppVersion: the minimum app version supported by this app. Earlier versions of this app will be forced to update to the current version. It should be a valid version string like this: ```2.0.13```. Overrides any minimum app version from UpgraderStore. Defaults to ```null```.
* storeController: a controller that provides the store details for each platform, defaults to `UpgraderStoreController()`.
* upgraderDevice: an abstraction of the device_info details which is used for the OS version, defaults to `UpgraderDevice()`.
* upgraderOS: information on which OS this code is running on, defaults to `UpgraderOS()`.
* willDisplayUpgrade: called when ```upgrader``` determines that an upgrade may
or may not be displayed, defaults to ```null```

The `UpgraderStoreController` class is a controller that provides the store details
for each platform.
* onAndroid: defaults to `UpgraderPlayStore()` that extends `UpgraderStore`.
* onFuchsia: defaults to `UpgraderAppStore()` that extends `UpgraderStore`.
* oniOS: defaults to `null`.
* onLinux: defaults to `null`.
* onMacOS: defaults to `null`.
* onWeb: defaults to `null`.
* onWindows: defaults to `null`.

To change the `UpgraderStore` for a platform, replace the platform with a
different store. Here is an example of using an Appcast on iOS.
```
final upgrader = Upgrader(
storeController: UpgraderStoreController(
onAndroid: () => UpgraderPlayStore(),
oniOS: () => UpgraderAppcastStore(appcastURL: appcastURL),
),
);
```

You can even subclass `UpgraderStore` or an existing store class like
`UpgraderPlayStore` to provide your own customization.

## Minimum App Version
The `upgrader` package can enforce a minimum app version simply by adding a
version number to the description field in the app stores.
Expand Down Expand Up @@ -204,7 +228,7 @@ a navigatorKey to the ```UpgradeAlert``` widget so that the correct route
context is used. Below is part of the code you will need for this. Also,
checkout the [example/lib/main-gorouter.dart](example/lib/main-gorouter.dart) example for a more complete example.

```
```dart
@override
Widget build(BuildContext context) {
return MaterialApp.router(
Expand Down Expand Up @@ -260,31 +284,33 @@ There is an [appcast](#appcast) that can be used to remotely configure the
latest app version. See [appcast](#appcast) below for more details.

## Appcast

The class [Appcast](lib/src/appcast.dart), in this Flutter package, is used by the `upgrader` widgets
to download app details from an appcast,
based on the [Sparkle](https://sparkle-project.org/) framework by Andy Matuschak.
You can read the Sparkle documentation here:
https://sparkle-project.org/documentation/publishing/.
The `upgrader` package supports Appcast as an `UpgraderStore`.

An appcast is an RSS feed with one channel that has a collection of items that each describe
one app version. The appcast will describe each app version and will provide the latest app
version to `upgrader` that indicates when an upgrade should be recommended.

Appcast is based on the [Sparkle](https://sparkle-project.org/) framework by Andy Matuschak.
You can read the Sparkle documentation here:
https://sparkle-project.org/documentation/publishing/.

The appcast must be hosted on a server that can be reached by everyone from the app. The appcast
XML file can be autogenerated during the release process, or just manually updated after a release
is available on the app store.

The Appcast class can be used stand alone or as part of `upgrader`.
The class [UpgraderAppcastStore](lib/src/upgrade_store_controller.dart), in this
Flutter package, is used by `upgrader` to download app details from an appcast.

### Appcast Example
This is an Appcast example for Android.
```dart
static const appcastURL =
'https://raw.githubusercontent.com/larryaasen/upgrader/master/test/testappcast.xml';
final upgrader = Upgrader(
appcastConfig:
AppcastConfiguration(url: appcastURL, supportedOS: ['android']));
storeController: UpgraderStoreController(
onAndroid: () => UpgraderAppcastStore(appcastURL: appcastURL),
),
);

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -419,22 +445,25 @@ class MySpanishMessages extends UpgraderMessages {
}
}

UpgradeAlert(Upgrader(messages: MySpanishMessages()));
UpgradeAlert(upgrader: Upgrader(messages: MySpanishMessages()));
```

You can even force the `upgrader` package to use a specific language, instead of the
system language on the device. Just pass the language code to an instance of
UpgraderMessages when displaying the alert or card. Here is an example:

```dart
UpgradeAlert(Upgrader(messages: UpgraderMessages(code: 'es')));
UpgradeAlert(upgrader: Upgrader(messages: UpgraderMessages(code: 'es')));
```

## Semantic Versioning

The `upgrader` package uses the [version](https://pub.dev/packages/version) package that
is in compliance with the Semantic Versioning spec at http://semver.org/.

is in compliance with the Semantic Versioning spec at http://semver.org/. It converts any
version string to a 3 digit version: MAJOR.MINOR.PATCH. For versions that only use 1
digit (MAJOR), it converts it to a 3 digit version: MAJOR.0.0, and for versions that
only use 2 digits (MAJOR.MINOR), it converts it to a 3 digit version: MAJOR.MINOR.0, to
be compliant with Semantic Versioning.

## iTunes Search API

Expand Down Expand Up @@ -498,29 +527,33 @@ which can be enabled by setting `debugLogging` to `true`.

It should look something like this:
```
flutter: upgrader: languageCode: en
flutter: upgrader: build UpgradeAlert
flutter: upgrader: default operatingSystem: ios 11.4
flutter: upgrader: operatingSystem: ios
flutter: upgrader: platform: TargetPlatform.iOS
flutter: upgrader: package info packageName: com.google.Maps
flutter: upgrader: package info appName: Upgrader
flutter: upgrader: package info version: 1.0.0
flutter: upgrader: operatingSystem: ios, version: Version 17.0.1 (Build 21A342)
flutter: upgrader: packageInfo packageName: com.google.Maps
flutter: upgrader: packageInfo appName: Upgrader
flutter: upgrader: packageInfo version: 1.0.0
flutter: upgrader: current locale: en_US
flutter: upgrader: countryCode: US
flutter: upgrader: languageCode: en
flutter: upgrader: download: https://itunes.apple.com/lookup?bundleId=com.google.Maps&country=US&_cb=1708305624824631
flutter: upgrader: response statusCode: 200
flutter: upgrader: UpgraderAppStore: version info: appStoreListingURL: https://apps.apple.com/us/app/google-maps/id585027354?uo=4, appStoreVersion: 6.102.3, installedVersion: 1.0.0, isCriticalUpdate: null, minAppVersion: null, releaseNotes: Thanks for using Google Maps! This release brings bug fixes that improve our product to help you discover new places and navigate to them.
flutter: upgrader: need to evaluate version
flutter: upgrader: blocked: false
flutter: upgrader: debugDisplayAlways: false
flutter: upgrader: debugDisplayOnce: false
flutter: upgrader: hasAlerted: false
flutter: upgrader: appStoreVersion: 5.81
flutter: upgrader: installedVersion: 1.0.0
flutter: upgrader: minAppVersion: null
flutter: upgrader: isUpdateAvailable: true
flutter: upgrader: shouldDisplayUpgrade: true
flutter: upgrader: shouldDisplayReleaseNotes: true
flutter: upgrader: showDialog title: Update App?
flutter: upgrader: showDialog message: A new version of Upgrader is available! Version 5.81 is now available-you have 1.0.0.
flutter: upgrader: showDialog releaseNotes: Thanks for using Google Maps! This release brings bug fixes that improve our product to help you discover new places and navigate to them.
flutter: upgrader: current locale: en_US
flutter: upgrader: languageCode: en
flutter: upgrader: showTheDialog title: Update App?
flutter: upgrader: showTheDialog message: A new version of Upgrader is available! Version 6.102.3 is now available-you have 1.0.0.
flutter: upgrader: showTheDialog releaseNotes: Thanks for using Google Maps! This release brings bug fixes that improve our product to help you discover new places and navigate to them.
```

Also, please include the upgrader version number from the pubspec.lock file, which should look something like this:
```
upgrader:
Expand Down
49 changes: 4 additions & 45 deletions example/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,47 +1,6 @@
include: package:flutter_lints/flutter.yaml

linter:
rules:
- always_declare_return_types
- always_require_non_null_named_parameters
- annotate_overrides
- avoid_empty_else
- avoid_init_to_null
- avoid_null_checks_in_equality_operators
- avoid_relative_lib_imports
- avoid_return_types_on_setters
- avoid_shadowing_type_parameters
- avoid_types_as_parameter_names
- camel_case_extensions
- curly_braces_in_flow_control_structures
- empty_catches
- empty_constructor_bodies
- library_names
- library_prefixes
- no_duplicate_case_values
- null_closures
- omit_local_variable_types
- prefer_adjacent_string_concatenation
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_contains
- prefer_equal_for_default_values
- prefer_final_fields
- prefer_for_elements_to_map_fromIterable
- prefer_generic_function_type_aliases
- prefer_if_null_operators
- prefer_is_empty
- prefer_is_not_empty
- prefer_iterable_whereType
- prefer_single_quotes
- prefer_spread_collections
- recursive_getters
- slash_for_doc_comments
- type_init_formals
- unawaited_futures
- unnecessary_const
- unnecessary_new
- unnecessary_null_in_if_null_operators
- unnecessary_this
- unrelated_type_equality_checks
- use_function_type_syntax_for_parameters
- use_rethrow_when_possible
- valid_regexps
avoid_function_literals_in_foreach_calls: false
avoid_print: false
2 changes: 1 addition & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion 33
compileSdkVersion 34

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
Expand Down
19 changes: 0 additions & 19 deletions example/lib/generated_plugin_registrant.dart

This file was deleted.

Loading
Loading