Improve accessability

This commit is contained in:
problematicconsumer
2023-09-14 15:20:48 +03:30
parent 90fa8455ac
commit 6dff3a1841
7 changed files with 49 additions and 11 deletions

View File

@@ -29,10 +29,15 @@
"profile": { "profile": {
"overviewPageTitle": "Profiles", "overviewPageTitle": "Profiles",
"detailsPageTitle": "Profile", "detailsPageTitle": "Profile",
"activeProfileNameSemanticLabel": "Active profile name: ${name}",
"nonActiveProfileNameSemanticLabel": "Profile name: ${name}",
"activeProfileBtnSemanticLabel": "View all profiles",
"nonActiveProfileBtnSemanticLabel": "Select ${name} as active",
"subscription": { "subscription": {
"traffic": "Traffic", "traffic": "Traffic",
"updatedTimeAgo": "Updated ${timeago}", "updatedTimeAgo": "Updated ${timeago}",
"remainingDuration": "${duration} Days Remaining", "remainingDuration": "${duration} Days Remaining",
"remainingTrafficSemanticLabel": "${consumed} of ${total} traffic consumed",
"expired": "Expired", "expired": "Expired",
"noTraffic": "No more traffic" "noTraffic": "No more traffic"
}, },

View File

@@ -29,10 +29,15 @@
"profile": { "profile": {
"overviewPageTitle": "پروفایل‌ها", "overviewPageTitle": "پروفایل‌ها",
"detailsPageTitle": "پروفایل", "detailsPageTitle": "پروفایل",
"activeProfileNameSemanticLabel": "نام پروفایل فعال: ${name}",
"nonActiveProfileNameSemanticLabel": "نام پروفایل: ${name}",
"activeProfileBtnSemanticLabel": "همه‌ی پروفایل‌ها",
"nonActiveProfileBtnSemanticLabel": "انتخاب ${name} به عنوان پروفایل فعال",
"subscription": { "subscription": {
"traffic": "ترافیک", "traffic": "ترافیک",
"updatedTimeAgo": "بروزرسانی شده در ${timeago}", "updatedTimeAgo": "بروزرسانی شده در ${timeago}",
"remainingDuration": "${duration} روز باقی مانده", "remainingDuration": "${duration} روز باقی مانده",
"remainingTrafficSemanticLabel": "${consumed} از ${total} ترافیک مصرف شده",
"expired": "منقضی شده", "expired": "منقضی شده",
"noTraffic": "پایان ترافیک" "noTraffic": "پایان ترافیک"
}, },

View File

@@ -4,6 +4,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/core/core_providers.dart';
import 'package:hiddify/core/prefs/prefs.dart'; import 'package:hiddify/core/prefs/prefs.dart';
import 'package:hiddify/core/router/router.dart'; import 'package:hiddify/core/router/router.dart';
import 'package:hiddify/domain/constants.dart';
import 'package:hiddify/features/common/common_controllers.dart'; import 'package:hiddify/features/common/common_controllers.dart';
import 'package:hiddify/utils/utils.dart'; import 'package:hiddify/utils/utils.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
@@ -20,12 +21,13 @@ class AppView extends HookConsumerWidget with PresLogger {
ref.watch(commonControllersProvider); ref.watch(commonControllersProvider);
return MaterialApp.router( return MaterialApp.router(
builder: (context, child) { // builder: (context, child) {
return AccessibilityTools( // return AccessibilityTools(
checkFontOverflows: true, // checkFontOverflows: true,
child: child, // child: child,
); // );
}, // },
// showSemanticsDebugger: true,
routerConfig: router, routerConfig: router,
locale: locale, locale: locale,
supportedLocales: AppLocaleUtils.supportedLocales, supportedLocales: AppLocaleUtils.supportedLocales,
@@ -34,7 +36,7 @@ class AppView extends HookConsumerWidget with PresLogger {
themeMode: theme.mode, themeMode: theme.mode,
theme: theme.light(), theme: theme.light(),
darkTheme: theme.dark(), darkTheme: theme.dark(),
title: 'Hiddify Next', title: Constants.appName,
); );
} }
} }

View File

@@ -1,4 +1,5 @@
abstract class Constants { abstract class Constants {
static const appName = "Hiddify Next";
static const geoipFileName = "geoip.db"; static const geoipFileName = "geoip.db";
static const geositeFileName = "geosite.db"; static const geositeFileName = "geosite.db";
static const configsFolderName = "configs"; static const configsFolderName = "configs";

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/core/core_providers.dart';
@@ -48,7 +49,6 @@ class ProfileTile extends HookConsumerWidget {
profile.active ? theme.colorScheme.outlineVariant : Colors.transparent; profile.active ? theme.colorScheme.outlineVariant : Colors.transparent;
return Card( return Card(
semanticContainer: false,
margin: effectiveMargin, margin: effectiveMargin,
elevation: effectiveElevation, elevation: effectiveElevation,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@@ -62,7 +62,10 @@ class ProfileTile extends HookConsumerWidget {
children: [ children: [
SizedBox( SizedBox(
width: 48, width: 48,
child: ProfileActionButton(profile, !isMain), child: Semantics(
sortKey: const OrdinalSortKey(1),
child: ProfileActionButton(profile, !isMain),
),
), ),
VerticalDivider( VerticalDivider(
width: 1, width: 1,
@@ -71,9 +74,14 @@ class ProfileTile extends HookConsumerWidget {
Flexible( Flexible(
child: Semantics( child: Semantics(
button: true, button: true,
sortKey: isMain ? const OrdinalSortKey(0) : null,
focused: isMain,
liveRegion: isMain,
namesRoute: isMain,
label: isMain label: isMain
? t.profile.overviewPageTitle ? t.profile.activeProfileBtnSemanticLabel
: t.profile.edit.selectActiveTxt, : t.profile
.nonActiveProfileBtnSemanticLabel(name: profile.name),
child: InkWell( child: InkWell(
onTap: () { onTap: () {
if (isMain) { if (isMain) {
@@ -110,6 +118,10 @@ class ProfileTile extends HookConsumerWidget {
Flexible( Flexible(
child: Text( child: Text(
profile.name, profile.name,
semanticsLabel: t.profile
.activeProfileNameSemanticLabel(
name: profile.name,
),
style: theme.textTheme.titleMedium, style: theme.textTheme.titleMedium,
), ),
), ),
@@ -121,6 +133,10 @@ class ProfileTile extends HookConsumerWidget {
else else
Text( Text(
profile.name, profile.name,
semanticsLabel:
t.profile.nonActiveProfileNameSemanticLabel(
name: profile.name,
),
style: theme.textTheme.titleMedium, style: theme.textTheme.titleMedium,
), ),
if (subInfo != null) ...[ if (subInfo != null) ...[
@@ -320,6 +336,11 @@ class ProfileSubscriptionInfo extends HookConsumerWidget {
subInfo.total > 10 * 1099511627776 //10TB subInfo.total > 10 * 1099511627776 //10TB
? "∞ GiB" ? "∞ GiB"
: subInfo.consumption.sizeOf(subInfo.total), : subInfo.consumption.sizeOf(subInfo.total),
semanticsLabel:
t.profile.subscription.remainingTrafficSemanticLabel(
consumed: subInfo.consumption.sizeGB(),
total: subInfo.total.sizeGB(),
),
style: theme.textTheme.bodySmall, style: theme.textTheme.bodySmall,
), ),
), ),

View File

@@ -2,6 +2,7 @@ import 'dart:io';
import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/core/core_providers.dart';
import 'package:hiddify/domain/connectivity/connectivity.dart'; import 'package:hiddify/domain/connectivity/connectivity.dart';
import 'package:hiddify/domain/constants.dart';
import 'package:hiddify/features/common/connectivity/connectivity_controller.dart'; import 'package:hiddify/features/common/connectivity/connectivity_controller.dart';
import 'package:hiddify/features/common/window/window_controller.dart'; import 'package:hiddify/features/common/window/window_controller.dart';
import 'package:hiddify/gen/assets.gen.dart'; import 'package:hiddify/gen/assets.gen.dart';
@@ -22,6 +23,7 @@ class SystemTrayController extends _$SystemTrayController
_trayIconPath, _trayIconPath,
isTemplate: Platform.isMacOS, isTemplate: Platform.isMacOS,
); );
if (!Platform.isLinux) await trayManager.setToolTip(Constants.appName);
trayManager.addListener(this); trayManager.addListener(this);
_initialized = true; _initialized = true;
} }

View File

@@ -6,6 +6,8 @@ extension ByteFormatter on int {
static final _sizeOfFormat = static final _sizeOfFormat =
InformationSizeFormat(permissibleValueUnits: {InformationUnit.gibibyte}); InformationSizeFormat(permissibleValueUnits: {InformationUnit.gibibyte});
String sizeGB() => _sizeOfFormat.format(bytes());
String sizeOf(int total) => String sizeOf(int total) =>
"${_sizeOfFormat.format(bytes())} / ${_sizeOfFormat.format(total.bytes())}"; "${_sizeOfFormat.format(bytes())} / ${_sizeOfFormat.format(total.bytes())}";