about text
This commit is contained in:
parent
8c602894a6
commit
2fde531964
11 changed files with 422 additions and 2 deletions
72
lib/codefield.dart
Normal file
72
lib/codefield.dart
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_code_editor/flutter_code_editor.dart';
|
||||
|
||||
class WrappedCodeField extends StatefulWidget {
|
||||
final CodeController controller;
|
||||
final bool expands;
|
||||
final bool wrap;
|
||||
final TextStyle? textStyle;
|
||||
final Color? cursorColor;
|
||||
final EdgeInsets padding;
|
||||
final bool readOnly;
|
||||
final FocusNode? focusNode;
|
||||
|
||||
const WrappedCodeField({
|
||||
super.key,
|
||||
required this.controller,
|
||||
this.expands = false,
|
||||
this.wrap = true, // ✅ Enable wrapping by default
|
||||
this.textStyle,
|
||||
this.cursorColor,
|
||||
this.padding = EdgeInsets.zero,
|
||||
this.readOnly = false,
|
||||
this.focusNode,
|
||||
});
|
||||
|
||||
@override
|
||||
_WrappedCodeFieldState createState() => _WrappedCodeFieldState();
|
||||
}
|
||||
|
||||
class _WrappedCodeFieldState extends State<WrappedCodeField> {
|
||||
late FocusNode _focusNode;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_focusNode = widget.focusNode ?? FocusNode();
|
||||
_focusNode.attach(context, onKeyEvent: _onKeyEvent);
|
||||
}
|
||||
|
||||
KeyEventResult _onKeyEvent(FocusNode node, KeyEvent event) {
|
||||
return widget.controller.onKey(event);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: widget.padding,
|
||||
child: TextField(
|
||||
focusNode: _focusNode,
|
||||
controller: widget.controller,
|
||||
expands: widget.expands,
|
||||
minLines: widget.expands ? null : 1,
|
||||
maxLines: widget.expands ? null : null, // Allows text to grow dynamically
|
||||
scrollPhysics: widget.wrap ? const NeverScrollableScrollPhysics() : null,
|
||||
style: widget.textStyle ?? const TextStyle(fontSize: 16),
|
||||
cursorColor: widget.cursorColor ?? Colors.white,
|
||||
decoration: const InputDecoration(
|
||||
isCollapsed: true,
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
||||
),
|
||||
readOnly: widget.readOnly,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import 'package:device_apps/device_apps.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:plasmoid/read_only.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'day.dart';
|
||||
import 'night.dart';
|
||||
|
|
@ -356,6 +357,19 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> {
|
|||
return iconWidget;
|
||||
}
|
||||
|
||||
_showInfoPage(BuildContext context, String title, String content) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ReadOnlyPage(
|
||||
title: title,
|
||||
content: content,
|
||||
isDarkMode: widget.settings.darkTheme,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
|
@ -383,7 +397,7 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> {
|
|||
icon: SvgPicture.asset(
|
||||
"assets/plasmoid.svg",
|
||||
width: 30,
|
||||
color: Colors.orange,
|
||||
color: Color(0xff38818a),
|
||||
),
|
||||
onSelected: (String value) {
|
||||
switch (value) {
|
||||
|
|
@ -448,6 +462,9 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> {
|
|||
autoFocus: !widget.settings.autoFocus,
|
||||
));
|
||||
break;
|
||||
case 'About':
|
||||
_showInfoPage(context, "About", aboutContent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) => [
|
||||
|
|
@ -511,6 +528,13 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> {
|
|||
title: Text(widget.settings.autoFocus ? 'Disable Auto Focus' : 'Enable Auto Focus'),
|
||||
),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: 'About',
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.info_outline),
|
||||
title: Text('About'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -560,3 +584,28 @@ class _AppLauncherScreenState extends State<AppLauncherScreen> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
String aboutContent = """
|
||||
**Plasmoid** is a minimalist and opinionated app launcher for Android.
|
||||
|
||||
## Search & Launch:
|
||||
|
||||
Open Plasmoid and start typing in the search bar to filter your apps and shared files by name or tag.
|
||||
Tap an app to launch it immediately.
|
||||
|
||||
## Tagging:
|
||||
|
||||
Swipe right on any item to edit its tags. For shared files, a tag dialog appears immediately upon sharing.
|
||||
Tags help you organize items and are searchable using prefixes like @context, #general, or +project.
|
||||
|
||||
## Gestures & Settings:
|
||||
|
||||
Swipe left on an app to view its settings.
|
||||
Use the menu button (plasmoid) to toggle settings such as icon visibility, color mode, theme, sorting (alphabetically or by last used), and auto-focus.
|
||||
|
||||
---
|
||||
|
||||
Made with 💚 by randogothimport 'package:plasmoid/texts.dart';
|
||||
|
||||
Icon by [Game Icons.net](https://game-icons.net/).
|
||||
""";
|
||||
|
|
|
|||
81
lib/markdown.dart
Normal file
81
lib/markdown.dart
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import 'package:highlight/highlight.dart';
|
||||
|
||||
final markdown = Mode(refs: {}, aliases: [
|
||||
"md",
|
||||
"mkdown",
|
||||
"mkd"
|
||||
], contains: [
|
||||
Mode(className: "section", variants: [
|
||||
Mode(begin: "^#\\s{1,6}", end: "\$"),
|
||||
Mode(begin: "^.+?\\n[=-]{2,}\$")
|
||||
]),
|
||||
Mode(begin: "<", end: ">", subLanguage: ["xml"], relevance: 0),
|
||||
Mode(className: "bullet", begin: "^\\s*([*+-]|(\\d+\\.))\\s+"),
|
||||
Mode(className: "strong", begin: "[*_]{2}.+?[*_]{2}"),
|
||||
Mode(
|
||||
className: "emphasis",
|
||||
variants: [Mode(begin: "\\*.+?\\*"), Mode(begin: "_.+?_", relevance: 0)]),
|
||||
Mode(className: "quote", begin: "^>\\s+", end: "\$"),
|
||||
Mode(className: "code", variants: [
|
||||
Mode(begin: "^```\\w*\\s*\$", end: "^```[ ]*\$"),
|
||||
Mode(begin: "`.+?`"),
|
||||
Mode(begin: "^( {4}|\\t)", end: "\$", relevance: 0)
|
||||
]),
|
||||
Mode(begin: "^[-\\*]{3,}", end: "\$"),
|
||||
Mode(
|
||||
begin: "\\[.+?\\][\\(\\[].*?[\\)\\]]",
|
||||
returnBegin: true,
|
||||
contains: [
|
||||
Mode(
|
||||
className: "string",
|
||||
begin: "\\[",
|
||||
end: "\\]",
|
||||
excludeBegin: true,
|
||||
returnEnd: true,
|
||||
relevance: 0),
|
||||
Mode(
|
||||
className: "link",
|
||||
begin: "\\]\\(",
|
||||
end: "\\)",
|
||||
excludeBegin: true,
|
||||
excludeEnd: true),
|
||||
Mode(
|
||||
className: "symbol",
|
||||
begin: "\\]\\[",
|
||||
end: "\\]",
|
||||
excludeBegin: true,
|
||||
excludeEnd: true)
|
||||
],
|
||||
relevance: 10),
|
||||
Mode(begin: "^\\[[^\\n]+\\]:", returnBegin: true, contains: [
|
||||
Mode(
|
||||
className: "symbol",
|
||||
begin: "\\[",
|
||||
end: "\\]",
|
||||
excludeBegin: true,
|
||||
excludeEnd: true),
|
||||
Mode(className: "link", begin: ":\\s*", end: "\$", excludeBegin: true)
|
||||
]),
|
||||
|
||||
// Custom Tag Highlighting
|
||||
Mode(
|
||||
className: "tag-hash",
|
||||
begin: "(?<=\\s|^)#[a-zA-Z0-9_]+",
|
||||
relevance: 10), // Magenta
|
||||
Mode(
|
||||
className: "tag-plus",
|
||||
begin: "(?<=\\s|^)\\+[a-zA-Z0-9_]+",
|
||||
relevance: 10), // Cyan
|
||||
Mode(
|
||||
className: "tag-at",
|
||||
begin: "(?<=\\s|^)@[a-zA-Z0-9_]+",
|
||||
relevance: 10), // Yellow
|
||||
Mode(
|
||||
className: "keyword",
|
||||
begin: "(?<=\\s|^):[a-zA-Z0-9_]+",
|
||||
relevance: 10),
|
||||
Mode(
|
||||
className: "variable",
|
||||
begin: "(?<=\\s|^)\/[a-zA-Z0-9_\/]+",
|
||||
relevance: 10), // Yellow
|
||||
]);
|
||||
54
lib/read_only.dart
Normal file
54
lib/read_only.dart
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_code_editor/flutter_code_editor.dart';
|
||||
import 'markdown.dart';
|
||||
import 'day.dart';
|
||||
import 'night.dart';
|
||||
import 'codefield.dart'; // Ensure this includes WrappedCodeField
|
||||
|
||||
class ReadOnlyPage extends StatelessWidget {
|
||||
final String title;
|
||||
final String content;
|
||||
final bool isDarkMode;
|
||||
|
||||
ReadOnlyPage({
|
||||
required this.title,
|
||||
required this.content,
|
||||
required this.isDarkMode,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = isDarkMode ? nightTheme : dayTheme;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(title)),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: Image.asset(
|
||||
'assets/plasmoid_fg.png',
|
||||
width: 200,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
CodeTheme(
|
||||
data: CodeThemeData(styles: theme),
|
||||
child: WrappedCodeField(
|
||||
controller: CodeController(
|
||||
text: content,
|
||||
language: markdown,
|
||||
),
|
||||
wrap: true,
|
||||
readOnly: true,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 80)
|
||||
],
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue