diff --git a/CHANGELOG.md b/CHANGELOG.md index e42ad49..45b9bde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ * Fixes * New Features + +## Version 0.10.1 (beta) + +* Changes + * Adds Relatica User Agent string to API requests so that Friendica servers running >2023.06 + with blockbot enabled will allow requests. + * Adds version string to the settings screen to help users identify version installed + ## Version 0.10.0 (beta) * Changes diff --git a/install.md b/install.md index f42e4ed..c1634fb 100644 --- a/install.md +++ b/install.md @@ -6,12 +6,12 @@ For more information about the current beta testing program # Latest Binaries: -* Android v0.9.0 Is available by invitation through Play Store beta (please see me for access) - or [this self-installable ZIP file](https://mysocialportal-relatica.nyc3.cdn.digitaloceanspaces.com/v0.9.0/relatica_v0.9.0.apk.zip) -* iPhone/iPad v0.9.0: This is only available through TestFlight. Please contact me for access. -* [Windows (Intel) v0.9.0](https://mysocialportal-relatica.nyc3.cdn.digitaloceanspaces.com/v0.9.0/relatica_v0.9.0_win_x64.zip) -* macOS v0.9.0:This is only available through TestFlight. Please contact me for access. -* [Linux v0.9.0 (tested on Ubuntu 20 and 22)](https://mysocialportal-relatica.nyc3.cdn.digitaloceanspaces.com/v0.9.0/relatica_v0.9.0_linux_x64.zip) +* Android v0.10.1 Is available by invitation through Play Store beta (please see me for access) + or [this self-installable ZIP file](https://mysocialportal-relatica.nyc3.cdn.digitaloceanspaces.com/v0.10.1/relatica_v0.10.1.apk.zip) +* iPhone/iPad v0.10.1: This is only available through TestFlight. Please contact me for access. +* [Windows (Intel) v0.10.1](https://mysocialportal-relatica.nyc3.cdn.digitaloceanspaces.com/v0.10.1/relatica_v0.10.1_win_x64.zip) +* macOS v0.10.1:This is only available through TestFlight. Please contact me for access. +* [Linux v0.10.1 (tested on Ubuntu 20 and 22)](https://mysocialportal-relatica.nyc3.cdn.digitaloceanspaces.com/v0.10.1/relatica_v0.10.1_linux_x64.zip) ## Mobile diff --git a/lib/controls/login_aware_cached_network_image.dart b/lib/controls/login_aware_cached_network_image.dart index f8bb5c1..cd901f4 100644 --- a/lib/controls/login_aware_cached_network_image.dart +++ b/lib/controls/login_aware_cached_network_image.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; +import '../globals.dart'; import '../services/auth_service.dart'; class LoginAwareCachedNetworkImage extends StatelessWidget { @@ -22,12 +23,12 @@ class LoginAwareCachedNetworkImage extends StatelessWidget { Widget build(BuildContext context) { final profile = context.watch().currentProfile; - Map? headers; + Map headers = {'user-agent': userAgent}; try { final imageServer = Uri.parse(imageUrl).host; if (imageServer == profile.serverName) { - headers = {'Authorization': profile.credentials.authHeaderValue}; + headers['Authorization'] = profile.credentials.authHeaderValue; } } catch (e) { _logger.severe('Error Parsing ImageURL: $e'); diff --git a/lib/friendica_client/friendica_client.dart b/lib/friendica_client/friendica_client.dart index 7a0d6b7..b3a98ef 100644 --- a/lib/friendica_client/friendica_client.dart +++ b/lib/friendica_client/friendica_client.dart @@ -717,6 +717,7 @@ class RemoteFileClient extends FriendicaClient { url, headers: { 'Authorization': _profile.credentials.authHeaderValue, + 'user-agent': userAgent, }, ); @@ -742,6 +743,7 @@ class RemoteFileClient extends FriendicaClient { final postUri = Uri.parse('https://$serverName/api/friendica/photo/create'); final request = http.MultipartRequest('POST', postUri); request.headers['Authorization'] = _profile.credentials.authHeaderValue; + request.headers['user-agent'] = userAgent; if (usePhpDebugging) { request.headers['Cookie'] = 'XDEBUG_SESSION=PHPSTORM;path=/'; } diff --git a/lib/globals.dart b/lib/globals.dart index 03050e3..7642b10 100644 --- a/lib/globals.dart +++ b/lib/globals.dart @@ -19,6 +19,9 @@ final platformIsDesktop = !platformIsMobile; final useImagePicker = kIsWeb || platformIsMobile; +String appVersion = ''; +String userAgent = ''; + const usePhpDebugging = false; const maxViewPortalHeight = 750.0; diff --git a/lib/main.dart b/lib/main.dart index 7e1a85d..50f4974 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:media_kit/media_kit.dart'; import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart'; +import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; import 'app_theme.dart'; @@ -45,6 +46,7 @@ void main() async { await fixLetsEncryptCertOnOldAndroid(); await dependencyInjectionInitialization(); + await setupPackageInfoAndUserAgent(); runApp(DevicePreview( enabled: !kReleaseMode && enablePreview, @@ -52,6 +54,12 @@ void main() async { )); } +Future setupPackageInfoAndUserAgent() async { + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + appVersion = packageInfo.version; + userAgent = 'Relatica/$appVersion'; +} + class App extends StatelessWidget { const App({super.key}); diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 4fe2f86..49166e5 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -28,6 +28,7 @@ class SettingsScreen extends StatelessWidget { child: ResponsiveMaxWidth( child: ListView( children: [ + buildVersionString(), buildLowBandwidthWidget(settings), buildThemeWidget(settings), if (!kReleaseMode) buildColorBlindnessTestSettings(settings), @@ -40,6 +41,18 @@ class SettingsScreen extends StatelessWidget { )); } + Widget buildVersionString() { + return Center( + child: Text( + 'Relatica $appVersion', + style: const TextStyle( + decoration: TextDecoration.underline, + fontWeight: FontWeight.bold, + ), + ), + ); + } + Widget buildLowBandwidthWidget(SettingsService settings) { return ListTile( title: const Text('Low bandwidth mode'), diff --git a/lib/screens/splash.dart b/lib/screens/splash.dart index c25fc9c..ba0ec3c 100644 --- a/lib/screens/splash.dart +++ b/lib/screens/splash.dart @@ -29,7 +29,7 @@ class SplashScreen extends StatelessWidget { SvgPicture.asset('icon/relatica_logo.svg', width: 128), const VerticalPadding(), Text( - 'Relatica', + 'Relatica $appVersion', style: Theme.of(context).textTheme.headlineLarge, ), const VerticalPadding(), diff --git a/lib/utils/network_utils.dart b/lib/utils/network_utils.dart index c6db2b4..8fe36a7 100644 --- a/lib/utils/network_utils.dart +++ b/lib/utils/network_utils.dart @@ -19,6 +19,18 @@ enum _RequestType { const _expireDuration = Duration(seconds: 2); +class RelaticaUserAgentHttpClient extends http.BaseClient { + final http.Client _inner; + + RelaticaUserAgentHttpClient() : _inner = http.Client(); + + @override + Future send(http.BaseRequest request) { + request.headers['user-agent'] = userAgent; + return _inner.send(request); + } +} + class _CachedResponse { final _RequestType requestType; final Uri requestUri; @@ -112,7 +124,7 @@ class _ExpiringRequestCache { print('Returning cached response for $type => $url'); response = _responses[requestStub]?.response ?? http.Response('', 555); } else { - final request = http.get( + final request = RelaticaUserAgentHttpClient().get( url, headers: headers, ); @@ -184,7 +196,7 @@ FutureResult postUrl( requestHeaders['Cookie'] = 'XDEBUG_SESSION=PHPSTORM;path=/'; } try { - final request = http.post( + final request = RelaticaUserAgentHttpClient().post( url, headers: requestHeaders, body: jsonEncode(body), @@ -215,7 +227,7 @@ FutureResult putUrl( }) async { _logger.fine('PUT: $url \n Body: $body'); try { - final request = http.put( + final request = RelaticaUserAgentHttpClient().put( url, headers: headers, body: jsonEncode(body), @@ -246,7 +258,7 @@ FutureResult deleteUrl( }) async { _logger.fine('DELETE: $url'); try { - final request = http.delete( + final request = RelaticaUserAgentHttpClient().delete( url, headers: headers, body: jsonEncode(body), diff --git a/lib/utils/opengraph_preview_grabber.dart b/lib/utils/opengraph_preview_grabber.dart index 5eb7c57..efcddea 100644 --- a/lib/utils/opengraph_preview_grabber.dart +++ b/lib/utils/opengraph_preview_grabber.dart @@ -1,11 +1,11 @@ import 'dart:convert'; import 'package:html/parser.dart'; -import 'package:http/http.dart' as http; import 'package:result_monad/result_monad.dart'; import '../models/exec_error.dart'; import '../models/link_preview_data.dart'; +import 'network_utils.dart'; const ogTitleKey = 'og:title'; const ogDescriptionKey = 'og:description'; @@ -35,7 +35,7 @@ FutureResult getLinkPreview(String url) async { FutureResult>, dynamic> _getOpenGraphData( String url) async { return runCatchingAsync>>(() async { - final response = await http.get(Uri.parse(url)); + final response = await RelaticaUserAgentHttpClient().get(Uri.parse(url)); if (response.statusCode != 200) { return buildErrorResult( type: ErrorType.serverError, diff --git a/pubspec.lock b/pubspec.lock index a5d46cb..0499c74 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -253,10 +253,10 @@ packages: dependency: transitive description: name: dbus - sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" url: "https://pub.dev" source: hosted - version: "0.7.8" + version: "0.7.10" desktop_window: dependency: "direct main" description: @@ -926,7 +926,7 @@ packages: source: hosted version: "2.1.0" package_info_plus: - dependency: transitive + dependency: "direct main" description: name: package_info_plus sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017" @@ -1025,10 +1025,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.8" pointycastle: dependency: transitive description: @@ -1535,10 +1535,10 @@ packages: dependency: transitive description: name: wakelock_plus - sha256: f45a6c03aa3f8322e0a9d7f4a0482721c8789cb41d555407367650b8f9c26018 + sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "1.1.4" wakelock_plus_platform_interface: dependency: transitive description: @@ -1575,10 +1575,10 @@ packages: dependency: transitive description: name: win32 - sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 url: "https://pub.dev" source: hosted - version: "5.0.9" + version: "5.1.1" win32_registry: dependency: transitive description: