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

v.1.2.7 #123

Merged
merged 57 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
558274b
Show external links for media (#86)
crxssed7 Jun 24, 2023
636f75b
Improved settings and horizontal chip lists
Jul 15, 2023
3a6acca
Better button row on user pages and cleanup
Jul 17, 2023
0e94bdc
Improved switcher widgets and other visual elements
Jul 25, 2023
e7fd71b
Code cleanup and padding improvements
Jul 26, 2023
746ec2c
Merge remote-tracking branch 'origin/master' into dev
Jul 27, 2023
4bcf86b
Improved external link sorting, and bar chart sizing
Jul 27, 2023
8ce285f
Added language identification on external media links
Jul 29, 2023
dd4b37b
Fixed media external link sorting
Jul 29, 2023
f6ace81
Maintenance
Aug 19, 2023
30b3416
Reorganised discover logic
Aug 19, 2023
237d9e1
Modified searching logic
Aug 21, 2023
f5edcdc
Added site links to character/staff/studio pages
Aug 21, 2023
fbfb744
Fixed notification icon and feed badge
Aug 22, 2023
3edd1eb
Changed handling of certain padding
Aug 23, 2023
5dad1ba
Fixed padding and bottom bar layouts
Aug 25, 2023
4a19a2d
Updated versioning
Aug 26, 2023
7d4f0b6
Fixed settings spacing
Aug 26, 2023
12005d1
Updated screenshots
lotusprey Aug 29, 2023
9d958c7
Updated dependencies and fixed visual/lazy-loading bugs
Sep 10, 2023
ef83d41
Fixed activity page padding
Sep 12, 2023
6ad2821
Fixed and restructuring
Sep 26, 2023
4d2ddca
Finished calendar and restructured some files
Oct 1, 2023
f5a1e62
Pure theme option now not only makes dark themes black, but light the…
Oct 1, 2023
1f07ab4
Support more languages in the external links
Oct 2, 2023
44d1c4a
Fastlane setup
Oct 9, 2023
e8af8b6
Updated dependencies and other cleanup
Oct 10, 2023
703c502
Versioning and calendar fixes
Oct 13, 2023
edda57c
Fixed null exceptions
Oct 14, 2023
fe01a0d
Calendar filters are cached
Oct 14, 2023
7c79516
Made calendar date selection more flexible
Oct 14, 2023
4a07284
Merge
Oct 15, 2023
0037dd5
Minor touch ups and updated dependencies.
Oct 24, 2023
ef61c97
Improved html rendering
Oct 30, 2023
8a1d5cc
Render HTML description preview (#113)
nstrelow Nov 24, 2023
11098ea
Replaced navigation and authentication deep linking with go_router (#…
lotusprey Nov 24, 2023
c1f8aca
Fixed merging
Nov 24, 2023
a21b4d1
Fixed pie chart labels and media date displaying
Nov 25, 2023
9b3dea3
Add option to search in notes (#116)
dlsf Nov 26, 2023
cc821e0
Add comment reply button (#118)
dlsf Nov 28, 2023
27cb6b0
Reorganized files and updated dependencies
Nov 29, 2023
dbde37a
Clean up of some deep links
Dec 24, 2023
9ce90d8
Images open as pop ups and mentions work in HTML content
Jan 2, 2024
ea07037
Better account handling
Jan 2, 2024
f9dbd74
Deep linking on android
Jan 2, 2024
e4b771f
Confirmed IOS https deep linking as currently impossible
Jan 2, 2024
160437b
Fix AniList settings not updating
Jan 3, 2024
9bd8ee1
Adjustments in how score is represented
Jan 3, 2024
7afd4eb
Fix text padding in bar charts
Jan 3, 2024
a55a20e
Tapping a media ranking redirects to discover
Jan 3, 2024
206937e
Fix settings updating when page is closed
Jan 4, 2024
4019e6f
More cohesive button & chip design
Jan 7, 2024
0570f2a
Add list status for related media in the media page
Jan 7, 2024
3a77433
Updated version
Jan 7, 2024
96ad282
Update ios target version
Jan 8, 2024
abcc362
Clear comments
Jan 8, 2024
b0f724b
v.1.2.7
Jan 8, 2024
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
24 changes: 19 additions & 5 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,28 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- Deep links -> -->
<!-- <meta-data android:name="flutter_deeplinking_enabled" android:value="true" /> -->
<intent-filter android:autoVerify="true">
<!-- Deep linking -->
<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="app" />
<data android:host="otraku" android:pathPrefix="/auth" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="app" android:host="otraku" android:pathPrefix="/auth" />
<!-- <data android:scheme="https" android:host="anilist.co" /> -->
<data android:scheme="https" />
<data android:host="anilist.co" android:pathPrefix="/anime/" />
<data android:host="anilist.co" android:pathPrefix="/manga/" />
<data android:host="anilist.co" android:pathPrefix="/character/" />
<data android:host="anilist.co" android:pathPrefix="/staff/" />
<data android:host="anilist.co" android:pathPrefix="/studio/" />
<data android:host="anilist.co" android:pathPrefix="/review/" />
<data android:host="anilist.co" android:pathPrefix="/user/" />
<data android:host="anilist.co" android:pathPrefix="/activity/" />
</intent-filter>
</activity>
<meta-data android:name="flutterEmbedding" android:value="2" />
Expand Down
9 changes: 0 additions & 9 deletions android/app/src/profile/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,6 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- Deep links -> -->
<!-- <meta-data android:name="flutter_deeplinking_enabled" android:value="true" /> -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="app" android:host="otraku" android:pathPrefix="/auth" />
<!-- <data android:scheme="https" android:host="anilist.co" /> -->
</intent-filter>
</activity>
<meta-data android:name="flutterEmbedding" android:value="2" />
</application>
Expand Down
Empty file.
8 changes: 8 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/61.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- Collection searching goes through both titles and notes
- Activity replies have a "Reply" button for automatic mentions
- Tapping on markdown images opens them as a popup
- Tapping on user mentions is not handled as a link, but directly opens the user page
- Tapping on a ranking in a media's statistics page redirects to the discover tab with added filters
- Deep linking on android, if configured in settings
- List status on related media in media pages
- And other visual improvements and fixes
8 changes: 1 addition & 7 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
PODS:
- app_links (0.0.1):
- Flutter
- Flutter (1.0.0)
- flutter_local_notifications (0.0.1):
- Flutter
Expand All @@ -21,7 +19,6 @@ PODS:
- Flutter

DEPENDENCIES:
- app_links (from `.symlinks/plugins/app_links/ios`)
- Flutter (from `Flutter`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
Expand All @@ -35,8 +32,6 @@ SPEC REPOS:
- FMDB

EXTERNAL SOURCES:
app_links:
:path: ".symlinks/plugins/app_links/ios"
Flutter:
:path: Flutter
flutter_local_notifications:
Expand All @@ -53,14 +48,13 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/workmanager/ios"

SPEC CHECKSUMS:
app_links: 5ef33d0d295a89d9d16bb81b0e3b0d5f70d6c875
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6

PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d
Expand Down
6 changes: 3 additions & 3 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -514,7 +514,7 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -546,7 +546,7 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down
8 changes: 3 additions & 5 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<!-- Url launcher -->
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https</string>
<string>https</string>
</array>
<!-- Deep links -->
<key>FlutterDeepLinkingEnabled</key>
<true/>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand All @@ -41,8 +41,6 @@
</array>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<!-- <key>FlutterDeepLinkingEnabled</key> -->
<!-- <true/> -->
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
Expand Down
134 changes: 65 additions & 69 deletions lib/common/utils/api.dart
Original file line number Diff line number Diff line change
@@ -1,100 +1,96 @@
import 'dart:async';
import 'dart:convert';

import 'package:flutter/widgets.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart';
import 'package:otraku/common/utils/options.dart';
import 'package:otraku/common/utils/route_arg.dart';
import 'package:otraku/modules/auth/account.dart';

abstract class Api {
static final _url = Uri.parse('https://graphql.anilist.co');

static const _TOKEN_0 = 'token0';
static const _TOKEN_1 = 'token1';

static String? _accessToken;

// Save credentials to an account.
static Future<void> register(
int account,
String token,
int expiration,
) async {
if (account < 0 || account > 1) return;

await const FlutterSecureStorage().write(
key: account == 0 ? _TOKEN_0 : _TOKEN_1,
value: token,
);
static Future<bool> init() async {
if (Options().selectedAccount == null) return false;
final account = Options().accounts[Options().selectedAccount!];
if (DateTime.now().compareTo(account.expiration) >= 0) return false;

expiration = DateTime.now()
.add(Duration(seconds: expiration, days: -1))
.millisecondsSinceEpoch;

Options().setExpirationOf(account, expiration);
_accessToken = await const FlutterSecureStorage().read(key: _key(account));
return true;
}

// Try loading a saved account.
static Future<bool> logIn(int account) async {
if (account < 0 || account > 1) return false;
static bool hasActiveAccount() => _accessToken != null;

if (_accessToken == null) {
// Check the token's expiration date.
if (Options().expirationOf(account) != null) {
final date = DateTime.fromMillisecondsSinceEpoch(
Options().expirationOf(account)!,
);
if (DateTime.now().compareTo(date) >= 0) {
removeAccount(account);
return false;
}
}

// Try to acquire the token from the storage.
_accessToken = await const FlutterSecureStorage()
.read(key: account == 0 ? _TOKEN_0 : _TOKEN_1);

if (_accessToken == null) return false;
}
static Future<bool> selectAccount(int index) async {
if (index < 0 || index >= Options().accounts.length) return false;

// Fetch the viewer's id, if needed.
if (Options().idOf(account) == null) {
try {
final data = await get('query Id {Viewer {id}}');
Options().setIdOf(account, data['Viewer']?['id']);
if (Options().idOf(account) == null) {
_accessToken = null;
return false;
}
} catch (_) {
return false;
}
}
final account = Options().accounts[index];
if (DateTime.now().compareTo(account.expiration) >= 0) return false;

Options().selectedAccount = index;
_accessToken = await const FlutterSecureStorage().read(key: _key(account));
return true;
}

// Log out and show available accounts.
static Future<void> logOut() async {
static Future<void> unselectAccount() async {
_accessToken = null;
Options().selectedAccount = null;
final context = RouteArg.navKey.currentContext;
if (context == null) return;
Navigator.pushNamedAndRemoveUntil(context, RouteArg.auth, (_) => false);
}

// Remove a saved account.
static Future<void> removeAccount(int account) async {
Options().setIdOf(account, null);
Options().setExpirationOf(account, null);
await const FlutterSecureStorage()
.delete(key: account == 0 ? _TOKEN_0 : _TOKEN_1);
static Future<bool> addAccount(
String token,
int secondsLeftBeforeExpiration,
) async {
_accessToken = token;
try {
final data = await get('query Viewer {Viewer {id name avatar {large}}}');
final id = data['Viewer']?['id'];
final name = data['Viewer']?['name'];
final avatarUrl = data['Viewer']?['avatar']?['large'];
if (id == null || name == null || avatarUrl == null) {
_accessToken = null;
return false;
}

if (Options().accounts.indexWhere((a) => a.id == id) > -1) return true;

final expiration = DateTime.now()
.add(Duration(seconds: secondsLeftBeforeExpiration, days: -1));
final account = Account(
id: id,
name: name,
avatarUrl: avatarUrl,
expiration: expiration,
);

Options().accounts = [...Options().accounts, account];
await const FlutterSecureStorage()
.write(key: _key(account), value: token);
return true;
} catch (_) {
_accessToken = null;
return false;
}
}

static Future<void> removeAccount(int index) async {
final account = Options().accounts.elementAtOrNull(index);
if (account == null) return;

final selectedAccount = Options().selectedAccount;
if (selectedAccount != null && selectedAccount >= index) {
Options().selectedAccount = null;
}

await const FlutterSecureStorage().delete(key: _key(account));
Options().accounts.removeAt(index);
Options().accounts = Options().accounts;
}

static bool loggedIn() => _accessToken != null;
static String _key(Account account) => 'auth${account.id}';

// Send a request.
/// Send a GraphQL request.
static Future<Map<String, dynamic>> get(
String query, [
Map<String, dynamic> variables = const {},
Expand Down
Loading