add scrollbar

This commit is contained in:
Mike Schwörer 2025-04-18 13:15:33 +02:00
parent 24cd1692c6
commit 967ae915b2
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
4 changed files with 107 additions and 81 deletions

View File

@ -2,24 +2,24 @@
# TODO # TODO
- [x] Message List - [x] Message List
* [ ] CRUD * [x] CRUD
- [x] Message Big-View - [x] Message Big-View
- [x] Search/Filter Messages - [x] Search/Filter Messages
- [x] Channel List - [x] Channel List
* [x] Show subs * [x] Show subs
* [ ] CRUD * [x] CRUD
* [ ] what about unsubbed foreign channels? - thex should still be visible (or should they, do i still get the messages?) * [x] what about unsubbed foreign channels? - thex should still be visible (or should they, do i still get the messages?)
- [x] Sub List - [x] Sub List
* [x] Sub/Unsub/Accept/Deny * [x] Sub/Unsub/Accept/Deny
- [x] Debug List (Show logs, requests) - [x] Debug List (Show logs, requests)
- [ ] Key List - [x] Key List
* [ ] CRUD * [x] CRUD
- [ ] Auto R-only key for admin, use for QR+link+send - [x] Auto R-only key for admin, use for QR+link+send
- [ ] settings - [ ] settings
- [ ] notifications - [?] notifications
- [ ] push navigation stack - [?] push navigation stack
- [ ] read + migrate old SharedPrefs (or not? - who uses SCN even??) - [/] read + migrate old SharedPrefs (or not? - who uses SCN even??)
- [ ] Account-Page - [x] Account-Page
- [x] Logout - [x] Logout
- [x] Send-page - [x] Send-page
@ -27,10 +27,10 @@
- [x] fix time format (in message-list, in card, top right) - midnight is shown as "24:05" instead of "00:05" - thats weird - [x] fix time format (in message-list, in card, top right) - midnight is shown as "24:05" instead of "00:05" - thats weird
- [ ] Add scrollbar - [x] Add scrollbar
-> https://api.flutter.dev/flutter/material/Scrollbar-class.html -> https://api.flutter.dev/flutter/material/Scrollbar-class.html
- [ ] you cant unsubscribe from foreign channel without completely loosing subscription. - [x] you cant unsubscribe from foreign channel without completely loosing subscription.
perhaps subscriptions should have two cofirmed bool (both must be true to receive messages): confirmed-owner && confirmed-subscriber perhaps subscriptions should have two cofirmed bool (both must be true to receive messages): confirmed-owner && confirmed-subscriber
Then the subscriber can unconfirm his half - without loosing the owner confirmation Then the subscriber can unconfirm his half - without loosing the owner confirmation

View File

@ -31,10 +31,10 @@ if [ -z "$pids" ]; then
exit 1 exit 1
fi fi
trap 'echo "reseived SIGNAL<EXIT> - exiting"; exit 0' EXIT trap 'echo "reseived SIGNAL<EXIT> - exiting"; jobs -p | xargs kill ; exit 0' EXIT
trap 'echo "reseived SIGNAL<SIGINT> - exiting"; exit 0' SIGINT trap 'echo "reseived SIGNAL<SIGINT> - exiting"; jobs -p | xargs kill ; exit 0' SIGINT
trap 'echo "reseived SIGNAL<SIGTERM> - exiting"; exit 0' SIGTERM trap 'echo "reseived SIGNAL<SIGTERM> - exiting"; jobs -p | xargs kill ; exit 0' SIGTERM
trap 'echo "reseived SIGNAL<SIGQUIT> - exiting"; exit 0' SIGQUIT trap 'echo "reseived SIGNAL<SIGQUIT> - exiting"; jobs -p | xargs kill ; exit 0' SIGQUIT
echo "" echo ""
while IFS= read -r pid; do while IFS= read -r pid; do

View File

@ -37,6 +37,8 @@ class _MessageViewPageState extends State<MessageViewPage> {
(SCNMessage, ChannelPreview, KeyTokenPreview, UserPreview)? mainFutureSnapshot = null; (SCNMessage, ChannelPreview, KeyTokenPreview, UserPreview)? mainFutureSnapshot = null;
static final _dateFormat = DateFormat('yyyy-MM-dd HH:mm'); //TODO setting static final _dateFormat = DateFormat('yyyy-MM-dd HH:mm'); //TODO setting
final ScrollController _controller = ScrollController();
bool _monospaceMode = false; bool _monospaceMode = false;
SCNMessage? message = null; SCNMessage? message = null;
@ -83,6 +85,7 @@ class _MessageViewPageState extends State<MessageViewPage> {
@override @override
void dispose() { void dispose() {
_controller.dispose();
super.dispose(); super.dispose();
} }
@ -137,77 +140,100 @@ class _MessageViewPageState extends State<MessageViewPage> {
Widget _buildMessageView(BuildContext context, SCNMessage message, ChannelPreview? channel, KeyTokenPreview? token, UserPreview? user) { Widget _buildMessageView(BuildContext context, SCNMessage message, ChannelPreview? channel, KeyTokenPreview? token, UserPreview? user) {
final userAccUserID = context.select<AppAuth, String?>((v) => v.userID); final userAccUserID = context.select<AppAuth, String?>((v) => v.userID);
return SingleChildScrollView( final child = Padding(
child: Padding( padding: const EdgeInsets.fromLTRB(24, 16, 24, 16),
padding: const EdgeInsets.fromLTRB(24, 16, 24, 16), child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.stretch,
crossAxisAlignment: CrossAxisAlignment.stretch, children: [
children: [ ..._buildMessageHeader(context, message, channel),
..._buildMessageHeader(context, message, channel), SizedBox(height: 8),
SizedBox(height: 8), if (message.content != null) ..._buildMessageContent(context, message),
if (message.content != null) ..._buildMessageContent(context, message), SizedBox(height: 8),
SizedBox(height: 8), if (message.senderName != null)
if (message.senderName != null)
UI.metaCard(
context: context,
icon: FontAwesomeIcons.solidSignature,
title: 'Sender',
values: [message.senderName!],
mainAction: () => {
Navi.push(context, () => FilteredMessageViewPage(title: message.senderName!, filter: MessageFilter(senderNames: [message.senderName!])))
},
),
UI.metaCard( UI.metaCard(
context: context, context: context,
icon: FontAwesomeIcons.solidGearCode, icon: FontAwesomeIcons.solidSignature,
title: 'KeyToken', title: 'Sender',
values: [message.usedKeyID, token?.name ?? '...'], values: [message.senderName!],
mainAction: () => { mainAction: () => {
Navi.push(context, () => FilteredMessageViewPage(title: token?.name ?? message.usedKeyID, filter: MessageFilter(usedKeys: [message.usedKeyID]))) Navi.push(context, () => FilteredMessageViewPage(title: message.senderName!, filter: MessageFilter(senderNames: [message.senderName!])))
}, },
), ),
UI.metaCard( UI.metaCard(
context: context, context: context,
icon: FontAwesomeIcons.solidIdCardClip, icon: FontAwesomeIcons.solidGearCode,
title: 'MessageID', title: 'KeyToken',
values: [message.messageID, message.userMessageID ?? ''], values: [message.usedKeyID, token?.name ?? '...'],
), mainAction: () => {
UI.metaCard( Navi.push(context, () => FilteredMessageViewPage(title: token?.name ?? message.usedKeyID, filter: MessageFilter(usedKeys: [message.usedKeyID])))
context: context, },
icon: FontAwesomeIcons.solidSnake, ),
title: 'Channel', UI.metaCard(
values: [message.channelID, channel?.displayName ?? message.channelInternalName], context: context,
mainAction: (channel != null) icon: FontAwesomeIcons.solidIdCardClip,
? () { title: 'MessageID',
Navi.push(context, () => ChannelViewPage(channelID: channel.channelID, preloadedData: null, needsReload: null)); values: [message.messageID, message.userMessageID ?? ''],
} ),
: null, UI.metaCard(
), context: context,
UI.metaCard( icon: FontAwesomeIcons.solidSnake,
context: context, title: 'Channel',
icon: FontAwesomeIcons.solidTimer, values: [message.channelID, channel?.displayName ?? message.channelInternalName],
title: 'Timestamp', mainAction: (channel != null)
values: [message.timestamp], ? () {
), Navi.push(context, () => ChannelViewPage(channelID: channel.channelID, preloadedData: null, needsReload: null));
UI.metaCard( }
context: context, : null,
icon: FontAwesomeIcons.solidUser, ),
title: 'User', UI.metaCard(
values: [user?.userID ?? '...', user?.username ?? ''], context: context,
mainAction: () => {/*TODO*/}, icon: FontAwesomeIcons.solidTimer,
), title: 'Timestamp',
UI.metaCard( values: [message.timestamp],
context: context, ),
icon: FontAwesomeIcons.solidBolt, UI.metaCard(
title: 'Priority', context: context,
values: [_prettyPrintPriority(message.priority)], icon: FontAwesomeIcons.solidUser,
mainAction: () => {/*TODO*/}, title: 'User',
), values: [user?.userID ?? '...', user?.username ?? ''],
if (message.senderUserID == userAccUserID) UI.button(text: "Delete Message", onPressed: () {/*TODO*/}, color: Colors.red[900]), mainAction: () => {/*TODO*/},
], ),
), UI.metaCard(
context: context,
icon: FontAwesomeIcons.solidBolt,
title: 'Priority',
values: [_prettyPrintPriority(message.priority)],
mainAction: () => {/*TODO*/},
),
if (message.senderUserID == userAccUserID) UI.button(text: "Delete Message", onPressed: () {/*TODO*/}, color: Colors.red[900]),
],
), ),
); );
var showScrollbar = true;
if (!_monospaceMode && (message.content ?? '').length > 4096) showScrollbar = true;
if (_monospaceMode && (message.content ?? '').split('\n').length > 64) showScrollbar = true;
if (showScrollbar) {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 6, 0),
child: Scrollbar(
thickness: 12.0,
radius: Radius.circular(6),
thumbVisibility: false,
interactive: true,
controller: _controller,
child: SingleChildScrollView(
controller: _controller,
child: child,
),
),
);
} else {
return SingleChildScrollView(
child: child,
);
}
} }
String _resolveChannelName(ChannelPreview? channel, SCNMessage message) { String _resolveChannelName(ChannelPreview? channel, SCNMessage message) {

View File

@ -35,7 +35,7 @@ function send()
if (xhr.readyState !== 4) return; if (xhr.readyState !== 4) return;
console.log('Status: ' + xhr.status); console.log('Status: ' + xhr.status);
if (xhr.status === 200 || xhr.status === 401 || xhr.status === 403 || xhr.status === 412) if (xhr.status === 200 || xhr.status === 400 || xhr.status === 401 || xhr.status === 403 || xhr.status === 412)
{ {
let resp = JSON.parse(xhr.responseText); let resp = JSON.parse(xhr.responseText);
if (!resp.success || xhr.status !== 200) if (!resp.success || xhr.status !== 200)