Skip to content

Commit c339d1f

Browse files
committed
feat: enable Impeller and add workaround for broken image
This commit brings Impeller back to Android again. Specific image is broken with Impeller backend, no similar issues found on issue tracker. To prepare for the upcoming stable release in August, enable impeller on Android is required. For the broken image issue, till now we only found the redirect back icon in static server resource is affected, so this commit adds a workaround for it: instead of render the original image, replace it with icon and icon button. This change is what we DO NOT intend but have to, another possible workaround is on the cache layer, but it is less semantic for users.
1 parent 114b1c0 commit c339d1f

File tree

7 files changed

+44
-6
lines changed

7 files changed

+44
-6
lines changed

android/app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,5 @@
3434
<meta-data
3535
android:name="flutterEmbedding"
3636
android:value="2"/>
37-
<meta-data
38-
android:name="io.flutter.embedding.android.EnableImpeller"
39-
android:value="false"/>
4037
</application>
4138
</manifest>

lib/constants/url.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ String formatReplyThreadUrl(String fid, String tid) {
8181
/// Prefix in url to get fast reply window to a certain post.
8282
const replyPostWindowSuffix = '&infloat=yes&handlekey=reply&inajax=1&ajaxtarget=fwin_content_reply';
8383

84+
/// Url of images have rendering issue with Impeller.
85+
///
86+
/// The root cause is not clear, maybe corrupt cache content, but it works with skia backend so should not be it.
87+
/// Since these images are now for redirect back purpose, we could handle them specially although we didn't intend to
88+
/// do it before, we have to do it before the next upcoming stable release of Flutter in August, 2025.
89+
const tmpImpellerWorkaroundUrls = [
90+
'https://$baseHost/static/image/common/back.gif',
91+
'https://$baseHostAlt/static/image/common/back.gif',
92+
];
93+
8494
/// Target url to post a reply to another post in thread [tid], forum [fid].
8595
String formatReplyPostUrl(String fid, String tid) {
8696
return '$homePage?mod=post&infloat=yes&action=reply&fid=$fid&'

lib/i18n/en.i18n.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,5 +1148,6 @@
11481148
"notReplyToFloorTip": "Not reply to this floor",
11491149
"expandToolbarTip": "Expand toolbar",
11501150
"collapseToolbarTip": "Collapse toolbar"
1151-
}
1151+
},
1152+
"workaroundRedirect": "View conversation"
11521153
}

lib/i18n/zh-CN.i18n.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,5 +1148,6 @@
11481148
"notReplyToFloorTip": "不回复该楼层(改为回复楼主)",
11491149
"expandToolbarTip": "展开工具栏",
11501150
"collapseToolbarTip": "收起工具栏"
1151-
}
1151+
},
1152+
"workaroundRedirect": "查看对话"
11521153
}

lib/i18n/zh-TW.i18n.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,5 +1148,6 @@
11481148
"notReplyToFloorTip": "不回覆該樓層(改為回覆樓主)",
11491149
"expandToolbarTip": "展開工具列",
11501150
"collapseToolbarTip": "收起工具列"
1151-
}
1151+
},
1152+
"workaroundRedirect": "查看對話"
11521153
}

lib/utils/html/html_muncher.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import 'package:flutter/gestures.dart';
44
import 'package:flutter/material.dart';
55
import 'package:tsdm_client/constants/constants.dart';
66
import 'package:tsdm_client/constants/layout.dart';
7+
import 'package:tsdm_client/constants/url.dart';
78
import 'package:tsdm_client/extensions/build_context.dart';
89
import 'package:tsdm_client/extensions/string.dart';
910
import 'package:tsdm_client/extensions/universal_html.dart';
11+
import 'package:tsdm_client/i18n/strings.g.dart';
1012
import 'package:tsdm_client/shared/models/models.dart';
1113
import 'package:tsdm_client/utils/html/adaptive_color.dart';
1214
import 'package:tsdm_client/utils/html/css_parser.dart';
@@ -384,6 +386,23 @@ final class _Muncher with LoggerMixin {
384386
final hrefUrl = state.tapUrl;
385387
final imgWidth = element.attributes['width']?.parseToInt()?.toDouble();
386388
final imgHeight = element.attributes['height']?.parseToInt()?.toDouble();
389+
390+
// Show a button instead of the original image.
391+
if (tmpImpellerWorkaroundUrls.contains(url)) {
392+
return [
393+
WidgetSpan(
394+
child: IconButton(
395+
icon: Icon(Icons.navigate_before_outlined, color: Theme.of(context).colorScheme.tertiary),
396+
// Constrains size to fit line height.
397+
constraints: const BoxConstraints(maxWidth: 24, minWidth: 24, maxHeight: 24, minHeight: 24),
398+
padding: EdgeInsets.zero,
399+
tooltip: context.t.workaroundRedirect,
400+
onPressed: hrefUrl != null ? () async => context.dispatchAsUrl(hrefUrl) : null,
401+
),
402+
),
403+
];
404+
}
405+
387406
return [
388407
WidgetSpan(
389408
child: GestureDetector(

lib/widgets/cached_image/cached_image.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'dart:async';
33
import 'package:flutter/material.dart';
44
import 'package:shimmer/shimmer.dart';
55
import 'package:tsdm_client/constants/layout.dart';
6+
import 'package:tsdm_client/constants/url.dart';
67
import 'package:tsdm_client/extensions/color.dart';
78
import 'package:tsdm_client/features/cache/models/models.dart';
89
import 'package:tsdm_client/instance.dart';
@@ -94,6 +95,9 @@ class _CachedImageState extends State<CachedImage> with LoggerMixin {
9495
@override
9596
void initState() {
9697
super.initState();
98+
if (tmpImpellerWorkaroundUrls.contains(widget.imageUrl)) {
99+
return;
100+
}
97101
imageSub = getIt
98102
.get<ImageCacheProvider>()
99103
.response
@@ -109,6 +113,11 @@ class _CachedImageState extends State<CachedImage> with LoggerMixin {
109113

110114
@override
111115
Widget build(BuildContext context) {
116+
// Show an icon instead of the original image.
117+
if (tmpImpellerWorkaroundUrls.contains(widget.imageUrl)) {
118+
return Icon(Icons.navigate_before_outlined, color: Theme.of(context).colorScheme.tertiary);
119+
}
120+
112121
final Widget body;
113122
if (widget.imageUrl.isEmpty) {
114123
body = FallbackPicture(

0 commit comments

Comments
 (0)