60 lines
2.3 KiB
Dart
60 lines
2.3 KiB
Dart
import 'dart:io';
|
||
|
||
import 'package:flutter/widgets.dart';
|
||
|
||
import '../core/vfs.dart';
|
||
import '../l10n/tr.dart';
|
||
|
||
/// 화면에 보일 경로 (67): Android 는 "내장 저장소 › Download › 폴더", WebDAV 는 "☁ 서버 › 폴더", Windows 는 "D: › 폴더"
|
||
String friendlyPath(String path) {
|
||
if (isDav(path)) {
|
||
final d = DavPath.parse(path);
|
||
return ['${d.mark} ${d.serverLabel}', ...d.rel.split('/').where((s) => s.isNotEmpty)].join(' › ');
|
||
}
|
||
if (Platform.isAndroid || path.startsWith('/storage/')) {
|
||
final m = RegExp(r'^/storage/(emulated/\d+|[^/]+)(/.*)?$').firstMatch(path);
|
||
if (m != null) {
|
||
final root = m[1]!.startsWith('emulated/') ? tr('내장 저장소') : tr('SD 카드');
|
||
return [root, ...(m[2] ?? '').split('/').where((s) => s.isNotEmpty)].join(' › ');
|
||
}
|
||
}
|
||
final parts = path.split(RegExp(r'[\\/]')).where((s) => s.isNotEmpty).toList();
|
||
return parts.isEmpty ? path : parts.join(' › ');
|
||
}
|
||
|
||
/// 짧게: 끝의 [keep] 단계만 (앞은 "…"). 쌍이 여러 개여도 무엇이 무엇인지 보이게 (67)
|
||
String shortPath(String path, {int keep = 3}) {
|
||
final parts = friendlyPath(path).split(' › ');
|
||
return parts.length <= keep ? parts.join(' › ') : ['…', ...parts.sublist(parts.length - keep)].join(' › ');
|
||
}
|
||
|
||
/// [text] 를 [style] 로 한 줄에 그렸을 때의 폭
|
||
double textWidth(BuildContext context, String text, TextStyle style) {
|
||
final tp = TextPainter(
|
||
text: TextSpan(text: text, style: DefaultTextStyle.of(context).style.merge(style)),
|
||
textDirection: Directionality.of(context),
|
||
textScaler: MediaQuery.textScalerOf(context),
|
||
maxLines: 1)
|
||
..layout();
|
||
final w = tp.width;
|
||
tp.dispose();
|
||
return w;
|
||
}
|
||
|
||
/// [text] 가 [maxWidth] 를 넘으면 가운데를 "…" 로 줄인다 (앞 · 끝이 보이게 - 412 캡처 10/18, 갈 곳 막대)
|
||
String middleEllipsis(BuildContext context, String text, TextStyle style, double maxWidth) {
|
||
if (maxWidth <= 0) return '…';
|
||
if (textWidth(context, text, style) <= maxWidth) return text;
|
||
var lo = 0, hi = text.length;
|
||
String cut(int n) => '${text.substring(0, (n + 1) ~/ 2)}…${text.substring(text.length - n ~/ 2)}';
|
||
while (lo < hi) {
|
||
final mid = (lo + hi + 1) ~/ 2;
|
||
if (textWidth(context, cut(mid), style) <= maxWidth) {
|
||
lo = mid;
|
||
} else {
|
||
hi = mid - 1;
|
||
}
|
||
}
|
||
return lo == 0 ? '…' : cut(lo);
|
||
}
|