Compare commits
2 Commits
b9ad6d4fd0
...
af044a86bc
Author | SHA1 | Date | |
---|---|---|---|
af044a86bc | |||
4884d04a51 |
@ -125,5 +125,9 @@
|
|||||||
"settingsNetworkServerResetDescription": "Reset to the official server address of Solar Network.",
|
"settingsNetworkServerResetDescription": "Reset to the official server address of Solar Network.",
|
||||||
"settingsNetworkServerPreset": "Present HyperNet Server",
|
"settingsNetworkServerPreset": "Present HyperNet Server",
|
||||||
"settingsNetworkServerPresetDescription": "You can choose one of our preset HyperNet server addresses from the list on the right.",
|
"settingsNetworkServerPresetDescription": "You can choose one of our preset HyperNet server addresses from the list on the right.",
|
||||||
"settingsNetworkServerSaved": "Server address saved."
|
"settingsNetworkServerSaved": "Server address saved.",
|
||||||
|
"sensitiveContent": "Sensitive Content",
|
||||||
|
"sensitiveContentCollapsed": "Sensitive content has been collapsed.",
|
||||||
|
"sensitiveContentDescription": "This content has been marked as sensitive, and may not be suitable for all viewers.",
|
||||||
|
"sensitiveContentReveal": "Reveal"
|
||||||
}
|
}
|
||||||
|
@ -125,5 +125,9 @@
|
|||||||
"settingsNetworkServerResetDescription": "重设为 Solar Network 的服务器地址。",
|
"settingsNetworkServerResetDescription": "重设为 Solar Network 的服务器地址。",
|
||||||
"settingsNetworkServerPreset": "预设的 HyperNet 服务器",
|
"settingsNetworkServerPreset": "预设的 HyperNet 服务器",
|
||||||
"settingsNetworkServerPresetDescription": "你可以在旁边的列表中选择我们提供的预设 HyperNet 服务器地址。",
|
"settingsNetworkServerPresetDescription": "你可以在旁边的列表中选择我们提供的预设 HyperNet 服务器地址。",
|
||||||
"settingsNetworkServerSaved": "服务器地址已保存。"
|
"settingsNetworkServerSaved": "服务器地址已保存。",
|
||||||
|
"sensitiveContent": "敏感内容",
|
||||||
|
"sensitiveContentCollapsed": "敏感内容已折叠。",
|
||||||
|
"sensitiveContentDescription": "此内容已被标记,可能不适合所有人查看。",
|
||||||
|
"sensitiveContentReveal": "显示内容"
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,6 @@
|
|||||||
64FBE78F9C282712818D6D95 /* Pods-RunnerTests.release.xcconfig */,
|
64FBE78F9C282712818D6D95 /* Pods-RunnerTests.release.xcconfig */,
|
||||||
96081771773FA019A97CCC3F /* Pods-RunnerTests.profile.xcconfig */,
|
96081771773FA019A97CCC3F /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
name = Pods;
|
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@ -474,6 +473,7 @@
|
|||||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@ -657,6 +657,7 @@
|
|||||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@ -680,6 +681,7 @@
|
|||||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>Surface</string>
|
<string>Solian</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>surface</string>
|
<string>Solian</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
|
@ -47,13 +47,11 @@ class _PostDetailScreenState extends State<PostDetailScreen> {
|
|||||||
resp.data['body']['attachments']?.cast<String>() ?? [],
|
resp.data['body']['attachments']?.cast<String>() ?? [],
|
||||||
);
|
);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
setState(() {
|
_data = SnPost.fromJson(resp.data).copyWith(
|
||||||
_data = SnPost.fromJson(resp.data).copyWith(
|
preload: SnPostPreload(
|
||||||
preload: SnPostPreload(
|
attachments: attachments,
|
||||||
attachments: attachments,
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
});
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
context.showErrorDialog(err);
|
context.showErrorDialog(err);
|
||||||
} finally {
|
} finally {
|
||||||
@ -87,13 +85,19 @@ class _PostDetailScreenState extends State<PostDetailScreen> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
flexibleSpace: Column(
|
flexibleSpace: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(_data?.body['title'] ?? 'postNoun'.tr())
|
if (_data?.body['title'] != null)
|
||||||
.textStyle(Theme.of(context).textTheme.titleLarge!)
|
Text(_data?.body['title'] ?? 'postNoun'.tr())
|
||||||
.textColor(Colors.white),
|
.textStyle(Theme.of(context).textTheme.titleLarge!)
|
||||||
Text('postDetail')
|
.textColor(Colors.white),
|
||||||
.tr()
|
if (_data?.body['title'] != null)
|
||||||
.textColor(Colors.white.withAlpha((255 * 0.9).round())),
|
Text('postDetail'.tr())
|
||||||
|
.textColor(Colors.white.withAlpha((255 * 0.9).round()))
|
||||||
|
else
|
||||||
|
Text('postDetail'.tr())
|
||||||
|
.textStyle(Theme.of(context).textTheme.titleLarge!)
|
||||||
|
.textColor(Colors.white),
|
||||||
],
|
],
|
||||||
).padding(top: math.max(MediaQuery.of(context).padding.top, 8)),
|
).padding(top: math.max(MediaQuery.of(context).padding.top, 8)),
|
||||||
),
|
),
|
||||||
@ -104,7 +108,10 @@ class _PostDetailScreenState extends State<PostDetailScreen> {
|
|||||||
),
|
),
|
||||||
if (_data != null)
|
if (_data != null)
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: PostItem(data: _data!, showComments: false),
|
child: PostItem(
|
||||||
|
data: _data!,
|
||||||
|
showComments: false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SliverToBoxAdapter(child: Divider(height: 1)),
|
const SliverToBoxAdapter(child: Divider(height: 1)),
|
||||||
if (_data != null)
|
if (_data != null)
|
||||||
|
@ -20,13 +20,13 @@ class SnPost with _$SnPost {
|
|||||||
required String? aliasPrefix,
|
required String? aliasPrefix,
|
||||||
required List<dynamic> tags,
|
required List<dynamic> tags,
|
||||||
required List<dynamic> categories,
|
required List<dynamic> categories,
|
||||||
required dynamic replies,
|
required List<SnPost>? replies,
|
||||||
required dynamic replyId,
|
required int? replyId,
|
||||||
required dynamic repostId,
|
required int? repostId,
|
||||||
required dynamic replyTo,
|
required SnPost? replyTo,
|
||||||
required dynamic repostTo,
|
required SnPost? repostTo,
|
||||||
required dynamic visibleUsersList,
|
required List<int>? visibleUsersList,
|
||||||
required dynamic invisibleUsersList,
|
required List<int>? invisibleUsersList,
|
||||||
required int visibility,
|
required int visibility,
|
||||||
required DateTime? editedAt,
|
required DateTime? editedAt,
|
||||||
required DateTime? pinnedAt,
|
required DateTime? pinnedAt,
|
||||||
|
@ -31,13 +31,13 @@ mixin _$SnPost {
|
|||||||
String? get aliasPrefix => throw _privateConstructorUsedError;
|
String? get aliasPrefix => throw _privateConstructorUsedError;
|
||||||
List<dynamic> get tags => throw _privateConstructorUsedError;
|
List<dynamic> get tags => throw _privateConstructorUsedError;
|
||||||
List<dynamic> get categories => throw _privateConstructorUsedError;
|
List<dynamic> get categories => throw _privateConstructorUsedError;
|
||||||
dynamic get replies => throw _privateConstructorUsedError;
|
List<SnPost>? get replies => throw _privateConstructorUsedError;
|
||||||
dynamic get replyId => throw _privateConstructorUsedError;
|
int? get replyId => throw _privateConstructorUsedError;
|
||||||
dynamic get repostId => throw _privateConstructorUsedError;
|
int? get repostId => throw _privateConstructorUsedError;
|
||||||
dynamic get replyTo => throw _privateConstructorUsedError;
|
SnPost? get replyTo => throw _privateConstructorUsedError;
|
||||||
dynamic get repostTo => throw _privateConstructorUsedError;
|
SnPost? get repostTo => throw _privateConstructorUsedError;
|
||||||
dynamic get visibleUsersList => throw _privateConstructorUsedError;
|
List<int>? get visibleUsersList => throw _privateConstructorUsedError;
|
||||||
dynamic get invisibleUsersList => throw _privateConstructorUsedError;
|
List<int>? get invisibleUsersList => throw _privateConstructorUsedError;
|
||||||
int get visibility => throw _privateConstructorUsedError;
|
int get visibility => throw _privateConstructorUsedError;
|
||||||
DateTime? get editedAt => throw _privateConstructorUsedError;
|
DateTime? get editedAt => throw _privateConstructorUsedError;
|
||||||
DateTime? get pinnedAt => throw _privateConstructorUsedError;
|
DateTime? get pinnedAt => throw _privateConstructorUsedError;
|
||||||
@ -78,13 +78,13 @@ abstract class $SnPostCopyWith<$Res> {
|
|||||||
String? aliasPrefix,
|
String? aliasPrefix,
|
||||||
List<dynamic> tags,
|
List<dynamic> tags,
|
||||||
List<dynamic> categories,
|
List<dynamic> categories,
|
||||||
dynamic replies,
|
List<SnPost>? replies,
|
||||||
dynamic replyId,
|
int? replyId,
|
||||||
dynamic repostId,
|
int? repostId,
|
||||||
dynamic replyTo,
|
SnPost? replyTo,
|
||||||
dynamic repostTo,
|
SnPost? repostTo,
|
||||||
dynamic visibleUsersList,
|
List<int>? visibleUsersList,
|
||||||
dynamic invisibleUsersList,
|
List<int>? invisibleUsersList,
|
||||||
int visibility,
|
int visibility,
|
||||||
DateTime? editedAt,
|
DateTime? editedAt,
|
||||||
DateTime? pinnedAt,
|
DateTime? pinnedAt,
|
||||||
@ -99,6 +99,8 @@ abstract class $SnPostCopyWith<$Res> {
|
|||||||
SnMetric metric,
|
SnMetric metric,
|
||||||
SnPostPreload? preload});
|
SnPostPreload? preload});
|
||||||
|
|
||||||
|
$SnPostCopyWith<$Res>? get replyTo;
|
||||||
|
$SnPostCopyWith<$Res>? get repostTo;
|
||||||
$SnPublisherCopyWith<$Res> get publisher;
|
$SnPublisherCopyWith<$Res> get publisher;
|
||||||
$SnMetricCopyWith<$Res> get metric;
|
$SnMetricCopyWith<$Res> get metric;
|
||||||
$SnPostPreloadCopyWith<$Res>? get preload;
|
$SnPostPreloadCopyWith<$Res>? get preload;
|
||||||
@ -199,31 +201,31 @@ class _$SnPostCopyWithImpl<$Res, $Val extends SnPost>
|
|||||||
replies: freezed == replies
|
replies: freezed == replies
|
||||||
? _value.replies
|
? _value.replies
|
||||||
: replies // ignore: cast_nullable_to_non_nullable
|
: replies // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as List<SnPost>?,
|
||||||
replyId: freezed == replyId
|
replyId: freezed == replyId
|
||||||
? _value.replyId
|
? _value.replyId
|
||||||
: replyId // ignore: cast_nullable_to_non_nullable
|
: replyId // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as int?,
|
||||||
repostId: freezed == repostId
|
repostId: freezed == repostId
|
||||||
? _value.repostId
|
? _value.repostId
|
||||||
: repostId // ignore: cast_nullable_to_non_nullable
|
: repostId // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as int?,
|
||||||
replyTo: freezed == replyTo
|
replyTo: freezed == replyTo
|
||||||
? _value.replyTo
|
? _value.replyTo
|
||||||
: replyTo // ignore: cast_nullable_to_non_nullable
|
: replyTo // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as SnPost?,
|
||||||
repostTo: freezed == repostTo
|
repostTo: freezed == repostTo
|
||||||
? _value.repostTo
|
? _value.repostTo
|
||||||
: repostTo // ignore: cast_nullable_to_non_nullable
|
: repostTo // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as SnPost?,
|
||||||
visibleUsersList: freezed == visibleUsersList
|
visibleUsersList: freezed == visibleUsersList
|
||||||
? _value.visibleUsersList
|
? _value.visibleUsersList
|
||||||
: visibleUsersList // ignore: cast_nullable_to_non_nullable
|
: visibleUsersList // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as List<int>?,
|
||||||
invisibleUsersList: freezed == invisibleUsersList
|
invisibleUsersList: freezed == invisibleUsersList
|
||||||
? _value.invisibleUsersList
|
? _value.invisibleUsersList
|
||||||
: invisibleUsersList // ignore: cast_nullable_to_non_nullable
|
: invisibleUsersList // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as List<int>?,
|
||||||
visibility: null == visibility
|
visibility: null == visibility
|
||||||
? _value.visibility
|
? _value.visibility
|
||||||
: visibility // ignore: cast_nullable_to_non_nullable
|
: visibility // ignore: cast_nullable_to_non_nullable
|
||||||
@ -279,6 +281,34 @@ class _$SnPostCopyWithImpl<$Res, $Val extends SnPost>
|
|||||||
) as $Val);
|
) as $Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a copy of SnPost
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnPostCopyWith<$Res>? get replyTo {
|
||||||
|
if (_value.replyTo == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnPostCopyWith<$Res>(_value.replyTo!, (value) {
|
||||||
|
return _then(_value.copyWith(replyTo: value) as $Val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of SnPost
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnPostCopyWith<$Res>? get repostTo {
|
||||||
|
if (_value.repostTo == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnPostCopyWith<$Res>(_value.repostTo!, (value) {
|
||||||
|
return _then(_value.copyWith(repostTo: value) as $Val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override
|
@override
|
||||||
@ -333,13 +363,13 @@ abstract class _$$SnPostImplCopyWith<$Res> implements $SnPostCopyWith<$Res> {
|
|||||||
String? aliasPrefix,
|
String? aliasPrefix,
|
||||||
List<dynamic> tags,
|
List<dynamic> tags,
|
||||||
List<dynamic> categories,
|
List<dynamic> categories,
|
||||||
dynamic replies,
|
List<SnPost>? replies,
|
||||||
dynamic replyId,
|
int? replyId,
|
||||||
dynamic repostId,
|
int? repostId,
|
||||||
dynamic replyTo,
|
SnPost? replyTo,
|
||||||
dynamic repostTo,
|
SnPost? repostTo,
|
||||||
dynamic visibleUsersList,
|
List<int>? visibleUsersList,
|
||||||
dynamic invisibleUsersList,
|
List<int>? invisibleUsersList,
|
||||||
int visibility,
|
int visibility,
|
||||||
DateTime? editedAt,
|
DateTime? editedAt,
|
||||||
DateTime? pinnedAt,
|
DateTime? pinnedAt,
|
||||||
@ -354,6 +384,10 @@ abstract class _$$SnPostImplCopyWith<$Res> implements $SnPostCopyWith<$Res> {
|
|||||||
SnMetric metric,
|
SnMetric metric,
|
||||||
SnPostPreload? preload});
|
SnPostPreload? preload});
|
||||||
|
|
||||||
|
@override
|
||||||
|
$SnPostCopyWith<$Res>? get replyTo;
|
||||||
|
@override
|
||||||
|
$SnPostCopyWith<$Res>? get repostTo;
|
||||||
@override
|
@override
|
||||||
$SnPublisherCopyWith<$Res> get publisher;
|
$SnPublisherCopyWith<$Res> get publisher;
|
||||||
@override
|
@override
|
||||||
@ -453,33 +487,33 @@ class __$$SnPostImplCopyWithImpl<$Res>
|
|||||||
: categories // ignore: cast_nullable_to_non_nullable
|
: categories // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,
|
as List<dynamic>,
|
||||||
replies: freezed == replies
|
replies: freezed == replies
|
||||||
? _value.replies
|
? _value._replies
|
||||||
: replies // ignore: cast_nullable_to_non_nullable
|
: replies // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as List<SnPost>?,
|
||||||
replyId: freezed == replyId
|
replyId: freezed == replyId
|
||||||
? _value.replyId
|
? _value.replyId
|
||||||
: replyId // ignore: cast_nullable_to_non_nullable
|
: replyId // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as int?,
|
||||||
repostId: freezed == repostId
|
repostId: freezed == repostId
|
||||||
? _value.repostId
|
? _value.repostId
|
||||||
: repostId // ignore: cast_nullable_to_non_nullable
|
: repostId // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as int?,
|
||||||
replyTo: freezed == replyTo
|
replyTo: freezed == replyTo
|
||||||
? _value.replyTo
|
? _value.replyTo
|
||||||
: replyTo // ignore: cast_nullable_to_non_nullable
|
: replyTo // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as SnPost?,
|
||||||
repostTo: freezed == repostTo
|
repostTo: freezed == repostTo
|
||||||
? _value.repostTo
|
? _value.repostTo
|
||||||
: repostTo // ignore: cast_nullable_to_non_nullable
|
: repostTo // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as SnPost?,
|
||||||
visibleUsersList: freezed == visibleUsersList
|
visibleUsersList: freezed == visibleUsersList
|
||||||
? _value.visibleUsersList
|
? _value._visibleUsersList
|
||||||
: visibleUsersList // ignore: cast_nullable_to_non_nullable
|
: visibleUsersList // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as List<int>?,
|
||||||
invisibleUsersList: freezed == invisibleUsersList
|
invisibleUsersList: freezed == invisibleUsersList
|
||||||
? _value.invisibleUsersList
|
? _value._invisibleUsersList
|
||||||
: invisibleUsersList // ignore: cast_nullable_to_non_nullable
|
: invisibleUsersList // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as List<int>?,
|
||||||
visibility: null == visibility
|
visibility: null == visibility
|
||||||
? _value.visibility
|
? _value.visibility
|
||||||
: visibility // ignore: cast_nullable_to_non_nullable
|
: visibility // ignore: cast_nullable_to_non_nullable
|
||||||
@ -551,13 +585,13 @@ class _$SnPostImpl extends _SnPost {
|
|||||||
required this.aliasPrefix,
|
required this.aliasPrefix,
|
||||||
required final List<dynamic> tags,
|
required final List<dynamic> tags,
|
||||||
required final List<dynamic> categories,
|
required final List<dynamic> categories,
|
||||||
required this.replies,
|
required final List<SnPost>? replies,
|
||||||
required this.replyId,
|
required this.replyId,
|
||||||
required this.repostId,
|
required this.repostId,
|
||||||
required this.replyTo,
|
required this.replyTo,
|
||||||
required this.repostTo,
|
required this.repostTo,
|
||||||
required this.visibleUsersList,
|
required final List<int>? visibleUsersList,
|
||||||
required this.invisibleUsersList,
|
required final List<int>? invisibleUsersList,
|
||||||
required this.visibility,
|
required this.visibility,
|
||||||
required this.editedAt,
|
required this.editedAt,
|
||||||
required this.pinnedAt,
|
required this.pinnedAt,
|
||||||
@ -574,6 +608,9 @@ class _$SnPostImpl extends _SnPost {
|
|||||||
: _body = body,
|
: _body = body,
|
||||||
_tags = tags,
|
_tags = tags,
|
||||||
_categories = categories,
|
_categories = categories,
|
||||||
|
_replies = replies,
|
||||||
|
_visibleUsersList = visibleUsersList,
|
||||||
|
_invisibleUsersList = invisibleUsersList,
|
||||||
super._();
|
super._();
|
||||||
|
|
||||||
factory _$SnPostImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$SnPostImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
@ -619,20 +656,46 @@ class _$SnPostImpl extends _SnPost {
|
|||||||
return EqualUnmodifiableListView(_categories);
|
return EqualUnmodifiableListView(_categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<SnPost>? _replies;
|
||||||
@override
|
@override
|
||||||
final dynamic replies;
|
List<SnPost>? get replies {
|
||||||
|
final value = _replies;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_replies is EqualUnmodifiableListView) return _replies;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(value);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final dynamic replyId;
|
final int? replyId;
|
||||||
@override
|
@override
|
||||||
final dynamic repostId;
|
final int? repostId;
|
||||||
@override
|
@override
|
||||||
final dynamic replyTo;
|
final SnPost? replyTo;
|
||||||
@override
|
@override
|
||||||
final dynamic repostTo;
|
final SnPost? repostTo;
|
||||||
|
final List<int>? _visibleUsersList;
|
||||||
@override
|
@override
|
||||||
final dynamic visibleUsersList;
|
List<int>? get visibleUsersList {
|
||||||
|
final value = _visibleUsersList;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_visibleUsersList is EqualUnmodifiableListView)
|
||||||
|
return _visibleUsersList;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<int>? _invisibleUsersList;
|
||||||
@override
|
@override
|
||||||
final dynamic invisibleUsersList;
|
List<int>? get invisibleUsersList {
|
||||||
|
final value = _invisibleUsersList;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_invisibleUsersList is EqualUnmodifiableListView)
|
||||||
|
return _invisibleUsersList;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(value);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final int visibility;
|
final int visibility;
|
||||||
@override
|
@override
|
||||||
@ -687,15 +750,17 @@ class _$SnPostImpl extends _SnPost {
|
|||||||
const DeepCollectionEquality().equals(other._tags, _tags) &&
|
const DeepCollectionEquality().equals(other._tags, _tags) &&
|
||||||
const DeepCollectionEquality()
|
const DeepCollectionEquality()
|
||||||
.equals(other._categories, _categories) &&
|
.equals(other._categories, _categories) &&
|
||||||
const DeepCollectionEquality().equals(other.replies, replies) &&
|
const DeepCollectionEquality().equals(other._replies, _replies) &&
|
||||||
const DeepCollectionEquality().equals(other.replyId, replyId) &&
|
(identical(other.replyId, replyId) || other.replyId == replyId) &&
|
||||||
const DeepCollectionEquality().equals(other.repostId, repostId) &&
|
(identical(other.repostId, repostId) ||
|
||||||
const DeepCollectionEquality().equals(other.replyTo, replyTo) &&
|
other.repostId == repostId) &&
|
||||||
const DeepCollectionEquality().equals(other.repostTo, repostTo) &&
|
(identical(other.replyTo, replyTo) || other.replyTo == replyTo) &&
|
||||||
|
(identical(other.repostTo, repostTo) ||
|
||||||
|
other.repostTo == repostTo) &&
|
||||||
const DeepCollectionEquality()
|
const DeepCollectionEquality()
|
||||||
.equals(other.visibleUsersList, visibleUsersList) &&
|
.equals(other._visibleUsersList, _visibleUsersList) &&
|
||||||
const DeepCollectionEquality()
|
const DeepCollectionEquality()
|
||||||
.equals(other.invisibleUsersList, invisibleUsersList) &&
|
.equals(other._invisibleUsersList, _invisibleUsersList) &&
|
||||||
(identical(other.visibility, visibility) ||
|
(identical(other.visibility, visibility) ||
|
||||||
other.visibility == visibility) &&
|
other.visibility == visibility) &&
|
||||||
(identical(other.editedAt, editedAt) ||
|
(identical(other.editedAt, editedAt) ||
|
||||||
@ -736,13 +801,13 @@ class _$SnPostImpl extends _SnPost {
|
|||||||
aliasPrefix,
|
aliasPrefix,
|
||||||
const DeepCollectionEquality().hash(_tags),
|
const DeepCollectionEquality().hash(_tags),
|
||||||
const DeepCollectionEquality().hash(_categories),
|
const DeepCollectionEquality().hash(_categories),
|
||||||
const DeepCollectionEquality().hash(replies),
|
const DeepCollectionEquality().hash(_replies),
|
||||||
const DeepCollectionEquality().hash(replyId),
|
replyId,
|
||||||
const DeepCollectionEquality().hash(repostId),
|
repostId,
|
||||||
const DeepCollectionEquality().hash(replyTo),
|
replyTo,
|
||||||
const DeepCollectionEquality().hash(repostTo),
|
repostTo,
|
||||||
const DeepCollectionEquality().hash(visibleUsersList),
|
const DeepCollectionEquality().hash(_visibleUsersList),
|
||||||
const DeepCollectionEquality().hash(invisibleUsersList),
|
const DeepCollectionEquality().hash(_invisibleUsersList),
|
||||||
visibility,
|
visibility,
|
||||||
editedAt,
|
editedAt,
|
||||||
pinnedAt,
|
pinnedAt,
|
||||||
@ -787,13 +852,13 @@ abstract class _SnPost extends SnPost {
|
|||||||
required final String? aliasPrefix,
|
required final String? aliasPrefix,
|
||||||
required final List<dynamic> tags,
|
required final List<dynamic> tags,
|
||||||
required final List<dynamic> categories,
|
required final List<dynamic> categories,
|
||||||
required final dynamic replies,
|
required final List<SnPost>? replies,
|
||||||
required final dynamic replyId,
|
required final int? replyId,
|
||||||
required final dynamic repostId,
|
required final int? repostId,
|
||||||
required final dynamic replyTo,
|
required final SnPost? replyTo,
|
||||||
required final dynamic repostTo,
|
required final SnPost? repostTo,
|
||||||
required final dynamic visibleUsersList,
|
required final List<int>? visibleUsersList,
|
||||||
required final dynamic invisibleUsersList,
|
required final List<int>? invisibleUsersList,
|
||||||
required final int visibility,
|
required final int visibility,
|
||||||
required final DateTime? editedAt,
|
required final DateTime? editedAt,
|
||||||
required final DateTime? pinnedAt,
|
required final DateTime? pinnedAt,
|
||||||
@ -834,19 +899,19 @@ abstract class _SnPost extends SnPost {
|
|||||||
@override
|
@override
|
||||||
List<dynamic> get categories;
|
List<dynamic> get categories;
|
||||||
@override
|
@override
|
||||||
dynamic get replies;
|
List<SnPost>? get replies;
|
||||||
@override
|
@override
|
||||||
dynamic get replyId;
|
int? get replyId;
|
||||||
@override
|
@override
|
||||||
dynamic get repostId;
|
int? get repostId;
|
||||||
@override
|
@override
|
||||||
dynamic get replyTo;
|
SnPost? get replyTo;
|
||||||
@override
|
@override
|
||||||
dynamic get repostTo;
|
SnPost? get repostTo;
|
||||||
@override
|
@override
|
||||||
dynamic get visibleUsersList;
|
List<int>? get visibleUsersList;
|
||||||
@override
|
@override
|
||||||
dynamic get invisibleUsersList;
|
List<int>? get invisibleUsersList;
|
||||||
@override
|
@override
|
||||||
int get visibility;
|
int get visibility;
|
||||||
@override
|
@override
|
||||||
|
@ -20,13 +20,23 @@ _$SnPostImpl _$$SnPostImplFromJson(Map<String, dynamic> json) => _$SnPostImpl(
|
|||||||
aliasPrefix: json['alias_prefix'] as String?,
|
aliasPrefix: json['alias_prefix'] as String?,
|
||||||
tags: json['tags'] as List<dynamic>,
|
tags: json['tags'] as List<dynamic>,
|
||||||
categories: json['categories'] as List<dynamic>,
|
categories: json['categories'] as List<dynamic>,
|
||||||
replies: json['replies'],
|
replies: (json['replies'] as List<dynamic>?)
|
||||||
replyId: json['reply_id'],
|
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
|
||||||
repostId: json['repost_id'],
|
.toList(),
|
||||||
replyTo: json['reply_to'],
|
replyId: (json['reply_id'] as num?)?.toInt(),
|
||||||
repostTo: json['repost_to'],
|
repostId: (json['repost_id'] as num?)?.toInt(),
|
||||||
visibleUsersList: json['visible_users_list'],
|
replyTo: json['reply_to'] == null
|
||||||
invisibleUsersList: json['invisible_users_list'],
|
? null
|
||||||
|
: SnPost.fromJson(json['reply_to'] as Map<String, dynamic>),
|
||||||
|
repostTo: json['repost_to'] == null
|
||||||
|
? null
|
||||||
|
: SnPost.fromJson(json['repost_to'] as Map<String, dynamic>),
|
||||||
|
visibleUsersList: (json['visible_users_list'] as List<dynamic>?)
|
||||||
|
?.map((e) => (e as num).toInt())
|
||||||
|
.toList(),
|
||||||
|
invisibleUsersList: (json['invisible_users_list'] as List<dynamic>?)
|
||||||
|
?.map((e) => (e as num).toInt())
|
||||||
|
.toList(),
|
||||||
visibility: (json['visibility'] as num).toInt(),
|
visibility: (json['visibility'] as num).toInt(),
|
||||||
editedAt: json['edited_at'] == null
|
editedAt: json['edited_at'] == null
|
||||||
? null
|
? null
|
||||||
@ -68,11 +78,11 @@ Map<String, dynamic> _$$SnPostImplToJson(_$SnPostImpl instance) =>
|
|||||||
'alias_prefix': instance.aliasPrefix,
|
'alias_prefix': instance.aliasPrefix,
|
||||||
'tags': instance.tags,
|
'tags': instance.tags,
|
||||||
'categories': instance.categories,
|
'categories': instance.categories,
|
||||||
'replies': instance.replies,
|
'replies': instance.replies?.map((e) => e.toJson()).toList(),
|
||||||
'reply_id': instance.replyId,
|
'reply_id': instance.replyId,
|
||||||
'repost_id': instance.repostId,
|
'repost_id': instance.repostId,
|
||||||
'reply_to': instance.replyTo,
|
'reply_to': instance.replyTo?.toJson(),
|
||||||
'repost_to': instance.repostTo,
|
'repost_to': instance.repostTo?.toJson(),
|
||||||
'visible_users_list': instance.visibleUsersList,
|
'visible_users_list': instance.visibleUsersList,
|
||||||
'invisible_users_list': instance.invisibleUsersList,
|
'invisible_users_list': instance.invisibleUsersList,
|
||||||
'visibility': instance.visibility,
|
'visibility': instance.visibility,
|
||||||
|
@ -28,6 +28,9 @@ class AttachmentDetailPopup extends StatelessWidget {
|
|||||||
tag: 'attachment-${data.rid}-${heroTag ?? uuid.v4()}',
|
tag: 'attachment-${data.rid}-${heroTag ?? uuid.v4()}',
|
||||||
child: PhotoView(
|
child: PhotoView(
|
||||||
key: Key('attachment-detail-${data.rid}-$heroTag'),
|
key: Key('attachment-detail-${data.rid}-$heroTag'),
|
||||||
|
backgroundDecoration: BoxDecoration(
|
||||||
|
color: Colors.black.withOpacity(0.7),
|
||||||
|
),
|
||||||
imageProvider: UniversalImage.provider(
|
imageProvider: UniversalImage.provider(
|
||||||
sn.getAttachmentUrl(data.rid),
|
sn.getAttachmentUrl(data.rid),
|
||||||
),
|
),
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:dismissible_page/dismissible_page.dart';
|
import 'package:dismissible_page/dismissible_page.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
import 'package:surface/types/attachment.dart';
|
import 'package:surface/types/attachment.dart';
|
||||||
import 'package:surface/widgets/attachment/attachment_detail.dart';
|
import 'package:surface/widgets/attachment/attachment_detail.dart';
|
||||||
@ -23,15 +29,11 @@ class AttachmentItem extends StatelessWidget {
|
|||||||
case 'image':
|
case 'image':
|
||||||
return Hero(
|
return Hero(
|
||||||
tag: 'attachment-${data.rid}-$heroTag',
|
tag: 'attachment-${data.rid}-$heroTag',
|
||||||
child: LayoutBuilder(builder: (context, constraints) {
|
child: AutoResizeUniversalImage(
|
||||||
return UniversalImage(
|
sn.getAttachmentUrl(data.rid),
|
||||||
sn.getAttachmentUrl(data.rid),
|
key: Key('attachment-${data.rid}-$heroTag'),
|
||||||
key: Key('attachment-${data.rid}-$heroTag'),
|
fit: BoxFit.cover,
|
||||||
fit: BoxFit.cover,
|
),
|
||||||
cacheHeight: constraints.maxHeight,
|
|
||||||
cacheWidth: constraints.maxWidth,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return const Placeholder();
|
return const Placeholder();
|
||||||
@ -43,6 +45,12 @@ class AttachmentItem extends StatelessWidget {
|
|||||||
final uuid = Uuid();
|
final uuid = Uuid();
|
||||||
final heroTag = uuid.v4();
|
final heroTag = uuid.v4();
|
||||||
|
|
||||||
|
if (data.isMature) {
|
||||||
|
return _AttachmentItemSensitiveBlur(
|
||||||
|
child: _buildContent(context, heroTag),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (isExpandable) {
|
if (isExpandable) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
child: _buildContent(context, heroTag),
|
child: _buildContent(context, heroTag),
|
||||||
@ -58,3 +66,87 @@ class AttachmentItem extends StatelessWidget {
|
|||||||
return _buildContent(context, heroTag);
|
return _buildContent(context, heroTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _AttachmentItemSensitiveBlur extends StatefulWidget {
|
||||||
|
final Widget child;
|
||||||
|
const _AttachmentItemSensitiveBlur({super.key, required this.child});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_AttachmentItemSensitiveBlur> createState() =>
|
||||||
|
_AttachmentItemSensitiveBlurState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AttachmentItemSensitiveBlurState
|
||||||
|
extends State<_AttachmentItemSensitiveBlur> {
|
||||||
|
bool _doesShow = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
widget.child,
|
||||||
|
ClipRect(
|
||||||
|
child: BackdropFilter(
|
||||||
|
filter: ImageFilter.blur(sigmaX: 40, sigmaY: 40),
|
||||||
|
child: Container(
|
||||||
|
color: Colors.black.withOpacity(0.5),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
Symbols.visibility_off,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 32,
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
Text('sensitiveContent')
|
||||||
|
.tr()
|
||||||
|
.fontSize(20)
|
||||||
|
.textColor(Colors.white)
|
||||||
|
.bold(),
|
||||||
|
Text('sensitiveContentDescription')
|
||||||
|
.tr()
|
||||||
|
.fontSize(14)
|
||||||
|
.textColor(Colors.white.withOpacity(0.8)),
|
||||||
|
const Gap(16),
|
||||||
|
InkWell(
|
||||||
|
child: Text('sensitiveContentReveal')
|
||||||
|
.tr()
|
||||||
|
.textColor(Colors.white),
|
||||||
|
onTap: () {
|
||||||
|
setState(() => _doesShow = !_doesShow);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.opacity(_doesShow ? 0 : 1, animate: true)
|
||||||
|
.animate(const Duration(milliseconds: 300), Curves.easeInOut),
|
||||||
|
if (_doesShow)
|
||||||
|
Positioned(
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
child: InkWell(
|
||||||
|
child: Icon(
|
||||||
|
Symbols.visibility_off,
|
||||||
|
color: Colors.white,
|
||||||
|
shadows: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.5),
|
||||||
|
blurRadius: 3,
|
||||||
|
offset: Offset(0, 1.5),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(all: 12),
|
||||||
|
onTap: () {
|
||||||
|
setState(() => _doesShow = !_doesShow);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -38,6 +38,11 @@ class PostItem extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
_PostContentHeader(data: data).padding(horizontal: 12, vertical: 8),
|
_PostContentHeader(data: data).padding(horizontal: 12, vertical: 8),
|
||||||
_PostContentBody(data: data.body).padding(horizontal: 16, bottom: 6),
|
_PostContentBody(data: data.body).padding(horizontal: 16, bottom: 6),
|
||||||
|
if (data.repostTo != null)
|
||||||
|
_PostQuoteContent(child: data.repostTo!).padding(
|
||||||
|
horizontal: 8,
|
||||||
|
bottom: 4,
|
||||||
|
),
|
||||||
if (data.preload?.attachments?.isNotEmpty ?? true)
|
if (data.preload?.attachments?.isNotEmpty ?? true)
|
||||||
AttachmentList(
|
AttachmentList(
|
||||||
data: data.preload!.attachments!,
|
data: data.preload!.attachments!,
|
||||||
@ -148,7 +153,13 @@ class _PostBottomAction extends StatelessWidget {
|
|||||||
|
|
||||||
class _PostContentHeader extends StatelessWidget {
|
class _PostContentHeader extends StatelessWidget {
|
||||||
final SnPost data;
|
final SnPost data;
|
||||||
const _PostContentHeader({required this.data});
|
final bool isCompact;
|
||||||
|
final bool showActions;
|
||||||
|
const _PostContentHeader({
|
||||||
|
required this.data,
|
||||||
|
this.isCompact = false,
|
||||||
|
this.showActions = true,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -157,13 +168,16 @@ class _PostContentHeader extends StatelessWidget {
|
|||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
AccountImage(content: data.publisher.avatar),
|
AccountImage(
|
||||||
const Gap(12),
|
content: data.publisher.avatar,
|
||||||
Expanded(
|
radius: isCompact ? 12 : 20,
|
||||||
child: Column(
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
Gap(isCompact ? 8 : 12),
|
||||||
|
if (isCompact)
|
||||||
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(data.publisher.nick).bold(),
|
Text(data.publisher.nick).bold(),
|
||||||
|
const Gap(4),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text('@${data.publisher.name}').fontSize(13),
|
Text('@${data.publisher.name}').fontSize(13),
|
||||||
@ -174,86 +188,104 @@ class _PostContentHeader extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
).opacity(0.8),
|
).opacity(0.8),
|
||||||
],
|
],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(data.publisher.nick).bold(),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text('@${data.publisher.name}').fontSize(13),
|
||||||
|
const Gap(4),
|
||||||
|
Text(RelativeTime(context).format(
|
||||||
|
data.publishedAt ?? data.createdAt,
|
||||||
|
)).fontSize(13),
|
||||||
|
],
|
||||||
|
).opacity(0.8),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
if (showActions)
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
icon: const Icon(Symbols.more_horiz),
|
icon: const Icon(Symbols.more_horiz),
|
||||||
style: const ButtonStyle(
|
style: const ButtonStyle(
|
||||||
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
|
||||||
),
|
),
|
||||||
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
|
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
|
||||||
if (isAuthor)
|
if (isAuthor)
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.edit),
|
||||||
|
const Gap(16),
|
||||||
|
Text('edit').tr(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed(
|
||||||
|
'postEditor',
|
||||||
|
pathParameters: {'mode': data.typePlural},
|
||||||
|
queryParameters: {'editing': data.id.toString()},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (isAuthor)
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.delete),
|
||||||
|
const Gap(16),
|
||||||
|
Text('delete').tr(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isAuthor) const PopupMenuDivider(),
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Symbols.edit),
|
const Icon(Symbols.reply),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
Text('edit').tr(),
|
Text('reply').tr(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed(
|
GoRouter.of(context).pushNamed(
|
||||||
'postEditor',
|
'postEditor',
|
||||||
pathParameters: {'mode': data.typePlural},
|
pathParameters: {'mode': data.typePlural},
|
||||||
queryParameters: {'editing': data.id.toString()},
|
queryParameters: {'replying': data.id.toString()},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (isAuthor)
|
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Symbols.delete),
|
const Icon(Symbols.forward),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
Text('delete').tr(),
|
Text('repost').tr(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed(
|
||||||
|
'postEditor',
|
||||||
|
pathParameters: {'mode': data.typePlural},
|
||||||
|
queryParameters: {'reposting': data.id.toString()},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const PopupMenuDivider(),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.flag),
|
||||||
|
const Gap(16),
|
||||||
|
Text('report').tr(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isAuthor) const PopupMenuDivider(),
|
],
|
||||||
PopupMenuItem(
|
),
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.reply),
|
|
||||||
const Gap(16),
|
|
||||||
Text('reply').tr(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
GoRouter.of(context).pushNamed(
|
|
||||||
'postEditor',
|
|
||||||
pathParameters: {'mode': data.typePlural},
|
|
||||||
queryParameters: {'replying': data.id.toString()},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.forward),
|
|
||||||
const Gap(16),
|
|
||||||
Text('repost').tr(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
GoRouter.of(context).pushNamed(
|
|
||||||
'postEditor',
|
|
||||||
pathParameters: {'mode': data.typePlural},
|
|
||||||
queryParameters: {'reposting': data.id.toString()},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const PopupMenuDivider(),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.flag),
|
|
||||||
const Gap(16),
|
|
||||||
Text('report').tr(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -269,3 +301,29 @@ class _PostContentBody extends StatelessWidget {
|
|||||||
return MarkdownTextContent(content: data['content']);
|
return MarkdownTextContent(content: data['content']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _PostQuoteContent extends StatelessWidget {
|
||||||
|
final SnPost child;
|
||||||
|
const _PostQuoteContent({super.key, required this.child});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
border: Border.all(
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_PostContentHeader(data: child, isCompact: true, showActions: false)
|
||||||
|
.padding(bottom: 4),
|
||||||
|
_PostContentBody(data: child.body),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
44
pubspec.lock
44
pubspec.lock
@ -5,23 +5,23 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
|
sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "76.0.0"
|
version: "72.0.0"
|
||||||
_macros:
|
_macros:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: dart
|
description: dart
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.3.3"
|
version: "0.3.2"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
|
sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.11.0"
|
version: "6.7.0"
|
||||||
animations:
|
animations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -202,10 +202,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
|
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.19.0"
|
version: "1.18.0"
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -790,18 +790,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.8"
|
version: "10.0.5"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.9"
|
version: "3.0.5"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -838,10 +838,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: macros
|
name: macros
|
||||||
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
|
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3-main.0"
|
version: "0.1.2-main.4"
|
||||||
markdown:
|
markdown:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1150,7 +1150,7 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.99"
|
||||||
source_gen:
|
source_gen:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1227,10 +1227,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.12.0"
|
version: "1.11.1"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1251,10 +1251,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
|
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.2.0"
|
||||||
styled_widget:
|
styled_widget:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1291,10 +1291,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.3"
|
version: "0.7.2"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1411,10 +1411,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
|
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.3.0"
|
version: "14.2.5"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -16,7 +16,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.0.0+1
|
version: 2.0.0+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.5.4
|
sdk: ^3.5.4
|
||||||
@ -166,4 +166,5 @@ flutter_native_splash:
|
|||||||
color_dark: "#000000"
|
color_dark: "#000000"
|
||||||
branding: "assets/icon/branding-light.png"
|
branding: "assets/icon/branding-light.png"
|
||||||
branding_dark: "assets/icon/branding-dark.png"
|
branding_dark: "assets/icon/branding-dark.png"
|
||||||
branding_bottom_padding: 24
|
branding_bottom_padding: 24
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user