dissolve app/ into repo root (D-056)
Single Flutter package at the repo root. All code, tests, assets, and platform directories moved from app/ to root. Package renamed from clide_app to clide — all imports rewritten. Merged pubspec combines core (ffi) and app (flutter, yaml, xterm) dependencies. Makefile simplified: no APP_PRESENT conditionals, no cd, no daemon lifecycle. 317 tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart' as flutter_services;
|
||||
|
||||
/// Typed, per-content-kind clipboard with a plaintext fallback.
|
||||
///
|
||||
/// Extensions write typed values (`write<GitHunk>(hunk)`) and read in
|
||||
/// the same type (`readAs<GitHunk>()`). Anything with a `toPlain`
|
||||
/// callback also syncs to the OS clipboard so external apps see
|
||||
/// reasonable text. The history ring keeps the last [historyLimit]
|
||||
/// entries per type for quick recall.
|
||||
class ClideClipboard {
|
||||
ClideClipboard({this.historyLimit = 16});
|
||||
|
||||
final int historyLimit;
|
||||
final Map<Type, List<Object>> _history = {};
|
||||
|
||||
Future<void> write<T extends Object>(
|
||||
T value, {
|
||||
String Function(T)? toPlain,
|
||||
}) async {
|
||||
final bucket = _history.putIfAbsent(T, () => <Object>[]);
|
||||
bucket.insert(0, value);
|
||||
if (bucket.length > historyLimit) bucket.removeLast();
|
||||
if (toPlain != null) {
|
||||
await flutter_services.Clipboard.setData(
|
||||
flutter_services.ClipboardData(text: toPlain(value)));
|
||||
}
|
||||
}
|
||||
|
||||
T? readAs<T extends Object>() {
|
||||
final bucket = _history[T];
|
||||
if (bucket == null || bucket.isEmpty) return null;
|
||||
return bucket.first as T;
|
||||
}
|
||||
|
||||
List<T> historyOf<T extends Object>() {
|
||||
final bucket = _history[T];
|
||||
if (bucket == null) return const [];
|
||||
return bucket.cast<T>().toList(growable: false);
|
||||
}
|
||||
|
||||
Future<String?> readPlain() async {
|
||||
final d = await flutter_services.Clipboard.getData('text/plain');
|
||||
return d?.text;
|
||||
}
|
||||
|
||||
Future<void> writePlain(String text) async {
|
||||
await flutter_services.Clipboard.setData(
|
||||
flutter_services.ClipboardData(text: text));
|
||||
final bucket = _history.putIfAbsent(String, () => <Object>[]);
|
||||
bucket.insert(0, text);
|
||||
if (bucket.length > historyLimit) bucket.removeLast();
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
void clear() => _history.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user