mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-11-01 05:53:27 +01:00
Merge pull request #1643 from ImranR98/dev
- Bugfix: Include GitLab token in APK request (#1622) - Bugfix: Don't trim trailing slashes when parsing links (#1625) - Improve contrast of placeholder icon in dark mode (#1637) - Improve app loading times - Revert a previous change to background downloads - Add a "clear logs" button
This commit is contained in:
2
.flutter
2
.flutter
Submodule .flutter updated: 5dcb86f68f...a14f74ff3a
@@ -111,6 +111,14 @@ class GitLab extends AppSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
|
||||||
|
Map<String, dynamic> additionalSettings) async {
|
||||||
|
String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});
|
||||||
|
String optionalAuth = (PAT != null) ? 'private_token=$PAT' : '';
|
||||||
|
return '$apkUrl?$optionalAuth';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl,
|
String standardUrl,
|
||||||
|
|||||||
@@ -226,18 +226,26 @@ class _AppPageState extends State<AppPage> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
app?.icon != null
|
FutureBuilder(
|
||||||
? Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
future: appsProvider.updateAppIcon(app?.app.id),
|
||||||
GestureDetector(
|
builder: (ctx, val) {
|
||||||
child: Image.memory(
|
return app?.icon != null
|
||||||
app!.icon!,
|
? Row(
|
||||||
height: 150,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
gaplessPlayback: true,
|
children: [
|
||||||
),
|
GestureDetector(
|
||||||
onTap: () => pm.openApp(app.app.id),
|
onTap: app == null
|
||||||
)
|
? null
|
||||||
])
|
: () => pm.openApp(app.app.id),
|
||||||
: Container(),
|
child: Image.memory(
|
||||||
|
app!.icon!,
|
||||||
|
height: 150,
|
||||||
|
gaplessPlayback: true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
])
|
||||||
|
: Container();
|
||||||
|
}),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 25,
|
height: 25,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -354,7 +354,11 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
SliverFillRemaining(
|
SliverFillRemaining(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
appsProvider.apps.isEmpty ? tr('noApps') : tr('noAppsForFilter'),
|
appsProvider.apps.isEmpty
|
||||||
|
? appsProvider.loadingApps
|
||||||
|
? tr('pleaseWait')
|
||||||
|
: tr('noApps')
|
||||||
|
: tr('noAppsForFilter'),
|
||||||
style: Theme.of(context).textTheme.headlineMedium,
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
))),
|
))),
|
||||||
@@ -402,29 +406,36 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAppIcon(int appIndex) {
|
getAppIcon(int appIndex) {
|
||||||
return listedApps[appIndex].icon != null
|
return FutureBuilder(
|
||||||
? Image.memory(
|
future: appsProvider.updateAppIcon(listedApps[appIndex].app.id),
|
||||||
listedApps[appIndex].icon!,
|
builder: (ctx, val) {
|
||||||
gaplessPlayback: true,
|
return listedApps[appIndex].icon != null
|
||||||
)
|
? Image.memory(
|
||||||
: Row(
|
listedApps[appIndex].icon!,
|
||||||
mainAxisSize: MainAxisSize.min,
|
gaplessPlayback: true,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
)
|
||||||
children: [
|
: Row(
|
||||||
Transform(
|
mainAxisSize: MainAxisSize.min,
|
||||||
alignment: Alignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
transform: Matrix4.rotationZ(0.31),
|
children: [
|
||||||
child: Padding(
|
Transform(
|
||||||
padding: const EdgeInsets.all(15),
|
alignment: Alignment.center,
|
||||||
child: Image(
|
transform: Matrix4.rotationZ(0.31),
|
||||||
image: const AssetImage(
|
child: Padding(
|
||||||
'assets/graphics/icon_small.png'),
|
padding: const EdgeInsets.all(15),
|
||||||
color: Colors.white.withOpacity(0.3),
|
child: Image(
|
||||||
colorBlendMode: BlendMode.modulate,
|
image: const AssetImage(
|
||||||
gaplessPlayback: true,
|
'assets/graphics/icon_small.png'),
|
||||||
),
|
color: Theme.of(context).brightness ==
|
||||||
)),
|
Brightness.dark
|
||||||
]);
|
? Colors.white.withOpacity(0.4)
|
||||||
|
: Colors.white.withOpacity(0.3),
|
||||||
|
colorBlendMode: BlendMode.modulate,
|
||||||
|
gaplessPlayback: true,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getVersionText(int appIndex) {
|
getVersionText(int appIndex) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:flex_color_picker/flex_color_picker.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:obtainium/components/custom_app_bar.dart';
|
import 'package:obtainium/components/custom_app_bar.dart';
|
||||||
import 'package:obtainium/components/generated_form.dart';
|
import 'package:obtainium/components/generated_form.dart';
|
||||||
|
import 'package:obtainium/components/generated_form_modal.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/main.dart';
|
import 'package:obtainium/main.dart';
|
||||||
import 'package:obtainium/providers/apps_provider.dart';
|
import 'package:obtainium/providers/apps_provider.dart';
|
||||||
@@ -945,6 +946,25 @@ class _LogsDialogState extends State<LogsDialog> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
var cont = (await showDialog<Map<String, dynamic>?>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext ctx) {
|
||||||
|
return GeneratedFormModal(
|
||||||
|
title: tr('appLogs'),
|
||||||
|
items: const [],
|
||||||
|
initValid: true,
|
||||||
|
message: tr('removeFromObtainium'),
|
||||||
|
);
|
||||||
|
})) !=
|
||||||
|
null;
|
||||||
|
if (cont) {
|
||||||
|
logsProvider.clear();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(tr('remove'))),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|||||||
@@ -329,6 +329,10 @@ Future<Map<String, String>> getHeaders(String url,
|
|||||||
return returnHeaders;
|
return returnHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<PackageInfo>> getAllInstalledInfo() async {
|
||||||
|
return await pm.getInstalledPackages() ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
Future<PackageInfo?> getInstalledInfo(String? packageName,
|
Future<PackageInfo?> getInstalledInfo(String? packageName,
|
||||||
{bool printErr = true}) async {
|
{bool printErr = true}) async {
|
||||||
if (packageName != null) {
|
if (packageName != null) {
|
||||||
@@ -364,7 +368,9 @@ class AppsProvider with ChangeNotifier {
|
|||||||
foregroundStream = FGBGEvents.stream.asBroadcastStream();
|
foregroundStream = FGBGEvents.stream.asBroadcastStream();
|
||||||
foregroundSubscription = foregroundStream?.listen((event) async {
|
foregroundSubscription = foregroundStream?.listen((event) async {
|
||||||
isForeground = event == FGBGType.foreground;
|
isForeground = event == FGBGType.foreground;
|
||||||
if (isForeground) loadApps();
|
if (isForeground) {
|
||||||
|
await loadApps();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
() async {
|
() async {
|
||||||
await settingsProvider.initializeSettings();
|
await settingsProvider.initializeSettings();
|
||||||
@@ -1160,17 +1166,6 @@ class AppsProvider with ChangeNotifier {
|
|||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateInstallStatusInMemory(AppInMemory app) async {
|
|
||||||
apps[app.app.id]?.installedInfo = await getInstalledInfo(app.app.id);
|
|
||||||
apps[app.app.id]?.icon =
|
|
||||||
await apps[app.app.id]?.installedInfo?.applicationInfo?.getAppIcon();
|
|
||||||
apps[app.app.id]?.app.name = await (apps[app.app.id]
|
|
||||||
?.installedInfo
|
|
||||||
?.applicationInfo
|
|
||||||
?.getAppLabel()) ??
|
|
||||||
app.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> loadApps({String? singleId}) async {
|
Future<void> loadApps({String? singleId}) async {
|
||||||
while (loadingApps) {
|
while (loadingApps) {
|
||||||
await Future.delayed(const Duration(microseconds: 1));
|
await Future.delayed(const Duration(microseconds: 1));
|
||||||
@@ -1179,6 +1174,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
var sp = SourceProvider();
|
var sp = SourceProvider();
|
||||||
List<List<String>> errors = [];
|
List<List<String>> errors = [];
|
||||||
|
var installedAppsData = await getAllInstalledInfo();
|
||||||
|
List<String> removedAppIds = [];
|
||||||
await Future.wait((await getAppsDir()) // Parse Apps from JSON
|
await Future.wait((await getAppsDir()) // Parse Apps from JSON
|
||||||
.listSync()
|
.listSync()
|
||||||
.map((item) async {
|
.map((item) async {
|
||||||
@@ -1199,43 +1196,53 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (app != null) {
|
if (app != null) {
|
||||||
|
// Save the app to the in-memory list without grabbing any OS info first
|
||||||
|
apps.update(
|
||||||
|
app.id,
|
||||||
|
(value) => AppInMemory(
|
||||||
|
app!, value.downloadProgress, value.installedInfo, value.icon),
|
||||||
|
ifAbsent: () => AppInMemory(app!, null, null, null));
|
||||||
|
notifyListeners();
|
||||||
try {
|
try {
|
||||||
|
// Try getting the app's source to ensure no invalid apps get loaded
|
||||||
sp.getSource(app.url, overrideSource: app.overrideSource);
|
sp.getSource(app.url, overrideSource: app.overrideSource);
|
||||||
|
// If the app is installed, grab its OS data and reconcile install statuses
|
||||||
|
PackageInfo? installedInfo;
|
||||||
|
try {
|
||||||
|
installedInfo =
|
||||||
|
installedAppsData.firstWhere((i) => i.packageName == app!.id);
|
||||||
|
} catch (e) {
|
||||||
|
// If the app isn't installed the above throws an error
|
||||||
|
}
|
||||||
|
// Reconcile differences between the installed and recorded install info
|
||||||
|
var moddedApp =
|
||||||
|
getCorrectedInstallStatusAppIfPossible(app, installedInfo);
|
||||||
|
if (moddedApp != null) {
|
||||||
|
app = moddedApp;
|
||||||
|
// Note the app ID if it was uninstalled externally
|
||||||
|
if (moddedApp.installedVersion == null) {
|
||||||
|
removedAppIds.add(moddedApp.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update the app in memory with install info and corrections
|
||||||
apps.update(
|
apps.update(
|
||||||
app.id,
|
app.id,
|
||||||
(value) => AppInMemory(app!, value.downloadProgress,
|
(value) => AppInMemory(
|
||||||
value.installedInfo, value.icon),
|
app!, value.downloadProgress, installedInfo, value.icon),
|
||||||
ifAbsent: () => AppInMemory(app!, null, null, null));
|
ifAbsent: () => AppInMemory(app!, null, installedInfo, null));
|
||||||
|
notifyListeners();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.add([app.id, app.finalName, e.toString()]);
|
errors.add([app!.id, app.finalName, e.toString()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
notifyListeners();
|
|
||||||
if (errors.isNotEmpty) {
|
if (errors.isNotEmpty) {
|
||||||
removeApps(errors.map((e) => e[0]).toList());
|
removeApps(errors.map((e) => e[0]).toList());
|
||||||
NotificationsProvider().notify(
|
NotificationsProvider().notify(
|
||||||
AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList()));
|
AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList()));
|
||||||
}
|
}
|
||||||
// Get install status and other OS info for each App (slow)
|
// Delete externally uninstalled Apps if needed
|
||||||
List<App> modifiedApps = [];
|
if (removedAppIds.isNotEmpty) {
|
||||||
await Future.wait(apps.values.map((app) async {
|
|
||||||
await updateInstallStatusInMemory(app);
|
|
||||||
var moddedApp =
|
|
||||||
getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo);
|
|
||||||
if (moddedApp != null) {
|
|
||||||
modifiedApps.add(moddedApp);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
notifyListeners();
|
|
||||||
// Reconcile version differences
|
|
||||||
if (modifiedApps.isNotEmpty) {
|
|
||||||
await saveApps(modifiedApps, attemptToCorrectInstallStatus: false);
|
|
||||||
var removedAppIds = modifiedApps
|
|
||||||
.where((a) => a.installedVersion == null)
|
|
||||||
.map((e) => e.id)
|
|
||||||
.toList();
|
|
||||||
// After reconciliation, delete externally uninstalled Apps if needed
|
|
||||||
if (removedAppIds.isNotEmpty) {
|
if (removedAppIds.isNotEmpty) {
|
||||||
if (settingsProvider.removeOnExternalUninstall) {
|
if (settingsProvider.removeOnExternalUninstall) {
|
||||||
await removeApps(removedAppIds);
|
await removeApps(removedAppIds);
|
||||||
@@ -1246,6 +1253,22 @@ class AppsProvider with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> updateAppIcon(String? appId) async {
|
||||||
|
if (apps[appId]?.icon == null) {
|
||||||
|
var icon =
|
||||||
|
(await apps[appId]?.installedInfo?.applicationInfo?.getAppIcon());
|
||||||
|
if (icon != null) {
|
||||||
|
apps.update(
|
||||||
|
apps[appId]!.app.id,
|
||||||
|
(value) => AppInMemory(apps[appId]!.app, value.downloadProgress,
|
||||||
|
value.installedInfo, icon),
|
||||||
|
ifAbsent: () => AppInMemory(
|
||||||
|
apps[appId]!.app, null, apps[appId]?.installedInfo, icon));
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> saveApps(List<App> apps,
|
Future<void> saveApps(List<App> apps,
|
||||||
{bool attemptToCorrectInstallStatus = true,
|
{bool attemptToCorrectInstallStatus = true,
|
||||||
bool onlyIfExists = true}) async {
|
bool onlyIfExists = true}) async {
|
||||||
@@ -1941,8 +1964,7 @@ Future<void> bgUpdateCheck(String taskId, Map<String, dynamic>? params) async {
|
|||||||
await appsProvider.downloadAndInstallLatestApps(
|
await appsProvider.downloadAndInstallLatestApps(
|
||||||
toInstall.map((e) => e.key).toList(), null,
|
toInstall.map((e) => e.key).toList(), null,
|
||||||
notificationsProvider: notificationsProvider,
|
notificationsProvider: notificationsProvider,
|
||||||
forceParallelDownloads: true,
|
forceParallelDownloads: true);
|
||||||
useExisting: false);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e is MultiAppMultiError) {
|
if (e is MultiAppMultiError) {
|
||||||
e.idsByErrorString.forEach((key, value) {
|
e.idsByErrorString.forEach((key, value) {
|
||||||
|
|||||||
@@ -354,11 +354,13 @@ preStandardizeUrl(String url) {
|
|||||||
url.toLowerCase().indexOf('https://') != 0) {
|
url.toLowerCase().indexOf('https://') != 0) {
|
||||||
url = 'https://$url';
|
url = 'https://$url';
|
||||||
}
|
}
|
||||||
|
var trailingSlash = Uri.tryParse(url)?.path.endsWith('/') ?? false;
|
||||||
url = url
|
url = url
|
||||||
.split('/')
|
.split('/')
|
||||||
.where((e) => e.isNotEmpty)
|
.where((e) => e.isNotEmpty)
|
||||||
.join('/')
|
.join('/')
|
||||||
.replaceFirst(':/', '://');
|
.replaceFirst(':/', '://') +
|
||||||
|
(trailingSlash ? '/' : '');
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,8 +525,7 @@ abstract class AppSource {
|
|||||||
[GeneratedFormTextField('appName', label: tr('appName'), required: false)],
|
[GeneratedFormTextField('appName', label: tr('appName'), required: false)],
|
||||||
[
|
[
|
||||||
GeneratedFormSwitch('shizukuPretendToBeGooglePlay',
|
GeneratedFormSwitch('shizukuPretendToBeGooglePlay',
|
||||||
label: tr('shizukuPretendToBeGooglePlay'),
|
label: tr('shizukuPretendToBeGooglePlay'), defaultValue: false)
|
||||||
defaultValue: false)
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
GeneratedFormSwitch('exemptFromBackgroundUpdates',
|
GeneratedFormSwitch('exemptFromBackgroundUpdates',
|
||||||
|
|||||||
24
pubspec.lock
24
pubspec.lock
@@ -47,18 +47,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: app_links
|
name: app_links
|
||||||
sha256: "8c6ef5ba9e26b720d4c9073826befb87df2ab5e7a81c22b6c3145080b5e736c9"
|
sha256: "96e677810b83707ff5e10fac11e4839daa0ea4e0123c35864c092699165eb3db"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.2"
|
version: "6.1.1"
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: archive
|
name: archive
|
||||||
sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265
|
sha256: "6bd38d335f0954f5fad9c79e614604fbf03a0e5b975923dd001b6ea965ef5b4b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.5.1"
|
version: "3.6.0"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -443,10 +443,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image
|
name: image
|
||||||
sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e"
|
sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.7"
|
version: "4.2.0"
|
||||||
intl:
|
intl:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -889,10 +889,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_android
|
name: url_launcher_android
|
||||||
sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775"
|
sha256: "17cd5e205ea615e2c6ea7a77323a11712dffa0720a8a90540db57a01347f9ad9"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.3.1"
|
version: "6.3.2"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -977,18 +977,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: webview_flutter
|
name: webview_flutter
|
||||||
sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932"
|
sha256: "6869c8786d179f929144b4a1f86e09ac0eddfe475984951ea6c634774c16b522"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.7.0"
|
version: "4.8.0"
|
||||||
webview_flutter_android:
|
webview_flutter_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_android
|
name: webview_flutter_android
|
||||||
sha256: dad3313c9ead95517bb1cae5e1c9d20ba83729d5a59e5e83c0a2d66203f27f91
|
sha256: "2282ba2320af34b2bd5320156c664d73f3f022341ed78847bc87723bf88c142f"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.16.1"
|
version: "3.16.2"
|
||||||
webview_flutter_platform_interface:
|
webview_flutter_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.1.9+2266
|
version: 1.1.10+2267
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
|
|||||||
Reference in New Issue
Block a user