init
This commit is contained in:
71
lib/configs/app_colors.dart
Normal file
71
lib/configs/app_colors.dart
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* @Author: Aimee~
|
||||
* @Date: 2022-06-02 11:38:05
|
||||
* @LastEditTime: 2022-06-21 10:03:25
|
||||
* @LastEditors: Aimee
|
||||
* @FilePath: /go_dao_vip/lib/configs/app_colors.dart
|
||||
* @Description:
|
||||
* @颜色出处: http://zhongguose.com/
|
||||
*/
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppColors {
|
||||
static const Color primary = Color(0xff34ce98); //
|
||||
|
||||
static const Color primaryDisable = Color.fromARGB(255, 25, 143, 101); //
|
||||
|
||||
static const Color deep = Color(0xff22aa98); //
|
||||
|
||||
static const Color success = Color(0xff5dbe8a); // 蔻梢绿
|
||||
|
||||
static const Color danger = Color(0xffc21f30); // 枫叶红
|
||||
|
||||
static const Color warning = Color(0xffebb10d); // 栀子黄
|
||||
|
||||
static const Color info = Color(0xff22a2c3); // 海青
|
||||
|
||||
static const Color black = Color(0xff22202e); // 暗龙胆紫
|
||||
|
||||
static const Color active = Color(0xff2d2e36); // 牛角灰
|
||||
|
||||
static const Color unactive = Color(0xff74759b); // 螺甸紫
|
||||
|
||||
static const Color page = Color(0xffF3F6FB); // 象牙白
|
||||
|
||||
static const Color nav = Color(0xffffffff);
|
||||
|
||||
static const Color border = Color(0xffe4dfd7); // 珍珠灰
|
||||
|
||||
static const Color blue = Color(0xff1890ff); // 拂晓蓝
|
||||
|
||||
static const Color darkBlue = Color(0xff11659a); // 搪磁蓝
|
||||
|
||||
static const Color red = Color(0xffff4d4f);
|
||||
|
||||
static const Color white = Color(0xffffffff);
|
||||
|
||||
static const Color transparent = Colors.transparent;
|
||||
|
||||
static const Color shadow = Color(0x1F000000);
|
||||
|
||||
static const Color golden = Color(0xfffca106); // 枇杷黄
|
||||
|
||||
static const Color mainBlack = Color(0xff000000);
|
||||
|
||||
static const Color tMainBg = Color(0xfff9f9f9);
|
||||
static const Color tVipBg = Color(0xff242430);
|
||||
static const Color tNack = Color(0xfffcc590);
|
||||
static const Color tNack1 = Color(0xfffcc692);
|
||||
static const Color tVip1 = Color(0xfffce3c5);
|
||||
static const Color tVip2 = Color(0xfffcc590);
|
||||
static const Color tVip3 = Color(0xff9f5529);
|
||||
static const Color tVip4 = Color(0xff3e5364);
|
||||
static const Color tVip5 = Color(0xff31364a);
|
||||
|
||||
static const Color tMainColor = Color(0xfffdbb03);
|
||||
static const Color tMainRedColor = Color(0xffe6576b);
|
||||
static const Color tTextColor = Color(0xff333333);
|
||||
static const Color tTextColor333 = Color(0xff333333);
|
||||
static const Color tTextColor666 = Color(0xff666666);
|
||||
static const Color tTextColor999 = Color(0xff999999);
|
||||
}
|
||||
24
lib/configs/app_size.dart
Normal file
24
lib/configs/app_size.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
class AppSize {
|
||||
/// 边距
|
||||
static const double verticalPadding = 8.0;
|
||||
static const double verticalLargePadding = 16.0;
|
||||
static const double horizontalPadding = 8.0;
|
||||
static const double horizontalLargePadding = 16.0;
|
||||
|
||||
static const double verticalMargin = 16.0;
|
||||
|
||||
/// 文本大小
|
||||
static const double titleFontSize = 18.0;
|
||||
static const double fontSize = 14.0;
|
||||
static const double smallFontSize = 10.0;
|
||||
|
||||
/// 分割线高度
|
||||
static const double dividerHeight = 0;
|
||||
|
||||
/// 边框尺寸
|
||||
static const double borderRadio = 8.0;
|
||||
static const double borderWidth = 0.4;
|
||||
static const double borderShadow = 8.0;
|
||||
}
|
||||
139
lib/configs/emoji.dart
Normal file
139
lib/configs/emoji.dart
Normal file
@@ -0,0 +1,139 @@
|
||||
List<Map<String, Object>> emojiData = [
|
||||
{"name": "GRINNING FACE WITH SMILING EYES", "unicode": 128513},
|
||||
{"name": "FACE WITH TEARS OF JOY", "unicode": 128514},
|
||||
{"name": "SMILING FACE WITH OPEN MOUTH", "unicode": 128515},
|
||||
{"name": "SMILING FACE WITH OPEN MOUTH AND SMILING EYES", "unicode": 128516},
|
||||
{"name": "SMILING FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128517},
|
||||
{
|
||||
"name": "SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES",
|
||||
"unicode": 128518
|
||||
},
|
||||
{"name": "WINKING FACE", "unicode": 128521},
|
||||
{"name": "SMILING FACE WITH SMILING EYES", "unicode": 128522},
|
||||
{"name": "FACE SAVOURING DELICIOUS FOOD", "unicode": 128523},
|
||||
{"name": "RELIEVED FACE", "unicode": 128524},
|
||||
{"name": "SMILING FACE WITH HEART-SHAPED EYES", "unicode": 128525},
|
||||
{"name": "SMIRKING FACE", "unicode": 128527},
|
||||
{"name": "UNAMUSED FACE", "unicode": 128530},
|
||||
{"name": "FACE WITH COLD SWEAT", "unicode": 128531},
|
||||
{"name": "PENSIVE FACE", "unicode": 128532},
|
||||
{"name": "CONFOUNDED FACE", "unicode": 128534},
|
||||
{"name": "FACE THROWING A KISS", "unicode": 128536},
|
||||
{"name": "KISSING FACE WITH CLOSED EYES", "unicode": 128538},
|
||||
{"name": "FACE WITH STUCK-OUT TONGUE AND WINKING EYE", "unicode": 128540},
|
||||
{
|
||||
"name": "FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES",
|
||||
"unicode": 128541
|
||||
},
|
||||
{"name": "DISAPPOINTED FACE", "unicode": 128542},
|
||||
{"name": "ANGRY FACE", "unicode": 128544},
|
||||
{"name": "POUTING FACE", "unicode": 128545},
|
||||
{"name": "CRYING FACE", "unicode": 128546},
|
||||
{"name": "PERSEVERING FACE", "unicode": 128547},
|
||||
{"name": "FACE WITH LOOK OF TRIUMPH", "unicode": 128548},
|
||||
{"name": "DISAPPOINTED BUT RELIEVED FACE", "unicode": 128549},
|
||||
{"name": "FEARFUL FACE", "unicode": 128552},
|
||||
{"name": "WEARY FACE", "unicode": 128553},
|
||||
{"name": "SLEEPY FACE", "unicode": 128554},
|
||||
{"name": "TIRED FACE", "unicode": 128555},
|
||||
{"name": "LOUDLY CRYING FACE", "unicode": 128557},
|
||||
{"name": "FACE WITH OPEN MOUTH AND COLD SWEAT", "unicode": 128560},
|
||||
{"name": "FACE SCREAMING IN FEAR", "unicode": 128561},
|
||||
{"name": "ASTONISHED FACE", "unicode": 128562},
|
||||
{"name": "FLUSHED FACE", "unicode": 128563},
|
||||
{"name": "DIZZY FACE", "unicode": 128565},
|
||||
{"name": "FACE WITH MEDICAL MASK", "unicode": 128567},
|
||||
{"name": "GRINNING CAT FACE WITH SMILING EYES", "unicode": 128568},
|
||||
{"name": "CAT FACE WITH TEARS OF JOY", "unicode": 128569},
|
||||
{"name": "SMILING CAT FACE WITH OPEN MOUTH", "unicode": 128570},
|
||||
{"name": "SMILING CAT FACE WITH HEART-SHAPED EYES", "unicode": 128571},
|
||||
{"name": "CAT FACE WITH WRY SMILE", "unicode": 128572},
|
||||
{"name": "KISSING CAT FACE WITH CLOSED EYES", "unicode": 128573},
|
||||
{"name": "POUTING CAT FACE", "unicode": 128574},
|
||||
{"name": "CRYING CAT FACE", "unicode": 128575},
|
||||
{"name": "WEARY CAT FACE", "unicode": 128576},
|
||||
{"name": "FACE WITH NO GOOD GESTURE", "unicode": 128581},
|
||||
{"name": "FACE WITH OK GESTURE", "unicode": 128582},
|
||||
{"name": "PERSON BOWING DEEPLY", "unicode": 128583},
|
||||
{"name": "SEE-NO-EVIL MONKEY", "unicode": 128584},
|
||||
{"name": "HEAR-NO-EVIL MONKEY", "unicode": 128585},
|
||||
{"name": "SPEAK-NO-EVIL MONKEY", "unicode": 128586},
|
||||
{"name": "HAPPY PERSON RAISING ONE HAND", "unicode": 128587},
|
||||
{"name": "PERSON RAISING BOTH HANDS IN CELEBRATION", "unicode": 128588},
|
||||
{"name": "PERSON FROWNING", "unicode": 128589},
|
||||
{"name": "PERSON WITH POUTING FACE", "unicode": 128590},
|
||||
{"name": "PERSON WITH FOLDED HANDS", "unicode": 128591},
|
||||
{"name": "BLACK SCISSORS", "unicode": 9986},
|
||||
{"name": "WHITE HEAVY CHECK MARK", "unicode": 9989},
|
||||
{"name": "AIRPLANE", "unicode": 9992},
|
||||
{"name": "ENVELOPE", "unicode": 9993},
|
||||
{"name": "RAISED FIST", "unicode": 9994},
|
||||
{"name": "RAISED HAND", "unicode": 9995},
|
||||
{"name": "VICTORY HAND", "unicode": 9996},
|
||||
{"name": "PENCIL", "unicode": 9999},
|
||||
{"name": "BLACK NIB", "unicode": 10002},
|
||||
{"name": "HEAVY CHECK MARK", "unicode": 10004},
|
||||
{"name": "HEAVY MULTIPLICATION X", "unicode": 10006},
|
||||
{"name": "SPARKLES", "unicode": 10024},
|
||||
{"name": "EIGHT SPOKED ASTERISK", "unicode": 10035},
|
||||
{"name": "EIGHT POINTED BLACK STAR", "unicode": 10036},
|
||||
{"name": "SNOWFLAKE", "unicode": 10052},
|
||||
{"name": "SPARKLE", "unicode": 10055},
|
||||
{"name": "CROSS MARK", "unicode": 10060},
|
||||
{"name": "NEGATIVE SQUARED CROSS MARK", "unicode": 10062},
|
||||
{"name": "BLACK QUESTION MARK ORNAMENT", "unicode": 10067},
|
||||
{"name": "WHITE QUESTION MARK ORNAMENT", "unicode": 10068},
|
||||
{"name": "WHITE EXCLAMATION MARK ORNAMENT", "unicode": 10069},
|
||||
{"name": "HEAVY EXCLAMATION MARK SYMBOL", "unicode": 10071},
|
||||
{"name": "HEAVY BLACK HEART", "unicode": 10084},
|
||||
{"name": "HEAVY PLUS SIGN", "unicode": 10133},
|
||||
{"name": "HEAVY MINUS SIGN", "unicode": 10134},
|
||||
{"name": "HEAVY DIVISION SIGN", "unicode": 10135},
|
||||
{"name": "BLACK RIGHTWARDS ARROW", "unicode": 10145},
|
||||
{"name": "CURLY LOOP", "unicode": 10160},
|
||||
{"name": "ROCKET", "unicode": 128640},
|
||||
{"name": "RAILWAY CAR", "unicode": 128643},
|
||||
{"name": "HIGH-SPEED TRAIN", "unicode": 128644},
|
||||
{"name": "HIGH-SPEED TRAIN WITH BULLET NOSE", "unicode": 128645},
|
||||
{"name": "METRO", "unicode": 128647},
|
||||
{"name": "STATION", "unicode": 128649},
|
||||
{"name": "BUS", "unicode": 128652},
|
||||
{"name": "BUS STOP", "unicode": 128655},
|
||||
{"name": "AMBULANCE", "unicode": 128657},
|
||||
{"name": "FIRE ENGINE", "unicode": 128658},
|
||||
{"name": "POLICE CAR", "unicode": 128659},
|
||||
{"name": "TAXI", "unicode": 128661},
|
||||
{"name": "AUTOMOBILE", "unicode": 128663},
|
||||
{"name": "RECREATIONAL VEHICLE", "unicode": 128665},
|
||||
{"name": "DELIVERY TRUCK", "unicode": 128666},
|
||||
{"name": "SHIP", "unicode": 128674},
|
||||
{"name": "SPEEDBOAT", "unicode": 128676},
|
||||
{"name": "HORIZONTAL TRAFFIC LIGHT", "unicode": 128677},
|
||||
{"name": "CONSTRUCTION SIGN", "unicode": 128679},
|
||||
{"name": "POLICE CARS REVOLVING LIGHT", "unicode": 128680},
|
||||
{"name": "TRIANGULAR FLAG ON POST", "unicode": 128681},
|
||||
{"name": "DOOR", "unicode": 128682},
|
||||
{"name": "NO ENTRY SIGN", "unicode": 128683},
|
||||
{"name": "SMOKING SYMBOL", "unicode": 128684},
|
||||
{"name": "NO SMOKING SYMBOL", "unicode": 128685},
|
||||
{"name": "BICYCLE", "unicode": 128690},
|
||||
{"name": "PEDESTRIAN", "unicode": 128694},
|
||||
{"name": "MENS SYMBOL", "unicode": 128697},
|
||||
{"name": "WOMENS SYMBOL", "unicode": 128698},
|
||||
{"name": "RESTROOM", "unicode": 128699},
|
||||
{"name": "BABY SYMBOL", "unicode": 128700},
|
||||
{"name": "TOILET", "unicode": 128701},
|
||||
{"name": "WATER CLOSET", "unicode": 128702},
|
||||
{"name": "BATH", "unicode": 128704},
|
||||
{"name": "CIRCLED LATIN CAPITAL LETTER M", "unicode": 9410},
|
||||
{"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER A", "unicode": 127344},
|
||||
{"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER B", "unicode": 127345},
|
||||
{"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER O", "unicode": 127358},
|
||||
{"name": "NEGATIVE SQUARED LATIN CAPITAL LETTER P", "unicode": 127359},
|
||||
{"name": "NEGATIVE SQUARED AB", "unicode": 127374},
|
||||
{"name": "SQUARED CL", "unicode": 127377},
|
||||
{"name": "SQUARED COOL", "unicode": 127378},
|
||||
{"name": "SQUARED FREE", "unicode": 127379},
|
||||
{"name": "SQUARED ID", "unicode": 127380},
|
||||
{"name": "SQUARED NEW", "unicode": 127381},
|
||||
];
|
||||
88
lib/configs/themes.dart
Normal file
88
lib/configs/themes.dart
Normal file
@@ -0,0 +1,88 @@
|
||||
import 'package:chat/configs/app_colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Themes {
|
||||
static final ThemeData light = ThemeData(
|
||||
/// 头部导航栏
|
||||
appBarTheme: const AppBarTheme(
|
||||
shadowColor: AppColors.transparent,
|
||||
color: AppColors.page,
|
||||
titleTextStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
color: AppColors.active,
|
||||
),
|
||||
foregroundColor: AppColors.active,
|
||||
),
|
||||
|
||||
/// 主色调
|
||||
primaryColor: AppColors.primary,
|
||||
primaryColorLight: AppColors.primary,
|
||||
|
||||
/// 按钮主题
|
||||
// elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
// style: ButtonStyle(
|
||||
// backgroundColor: MaterialStateProperty.all(
|
||||
// AppColors.primary,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
|
||||
/// 输入框光标颜色
|
||||
// textSelectionTheme: const TextSelectionThemeData(
|
||||
// cursorColor: AppColors.primary,
|
||||
// ),
|
||||
|
||||
toggleableActiveColor: AppColors.primary,
|
||||
|
||||
/// 脚手架的背景色,页面背景色
|
||||
scaffoldBackgroundColor: AppColors.page,
|
||||
indicatorColor: AppColors.active,
|
||||
splashColor: AppColors.transparent,
|
||||
highlightColor: AppColors.transparent,
|
||||
|
||||
/// 底部导航
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: AppColors.nav,
|
||||
selectedItemColor: AppColors.primary,
|
||||
unselectedItemColor: AppColors.unactive,
|
||||
selectedIconTheme: IconThemeData(color: AppColors.primary),
|
||||
unselectedIconTheme: IconThemeData(color: AppColors.unactive),
|
||||
selectedLabelStyle: TextStyle(
|
||||
fontSize: 11,
|
||||
),
|
||||
unselectedLabelStyle: TextStyle(
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
static final ThemeData dark = ThemeData(
|
||||
// appBarTheme: const AppBarTheme(
|
||||
// color: AppColors.active,
|
||||
// ),
|
||||
primaryColor: AppColors.danger,
|
||||
scaffoldBackgroundColor: AppColors.active,
|
||||
indicatorColor: AppColors.active,
|
||||
splashColor: AppColors.transparent,
|
||||
highlightColor: AppColors.transparent,
|
||||
hoverColor: AppColors.white.withOpacity(
|
||||
0.5,
|
||||
),
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: AppColors.active,
|
||||
selectedItemColor: AppColors.page,
|
||||
unselectedItemColor: AppColors.page,
|
||||
selectedLabelStyle: TextStyle(
|
||||
fontSize: 12,
|
||||
),
|
||||
unselectedLabelStyle: TextStyle(
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
drawerTheme: const DrawerThemeData(
|
||||
backgroundColor: AppColors.active,
|
||||
),
|
||||
);
|
||||
}
|
||||
40
lib/main.dart
Normal file
40
lib/main.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
import 'package:chat/configs/themes.dart';
|
||||
import 'package:chat/routes/app_router.dart';
|
||||
import 'package:chat/services/auth_service.dart';
|
||||
import 'package:chat/services/tabbar_service.dart';
|
||||
import 'package:chat/services/tim_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
await GetStorage.init();
|
||||
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetMaterialApp(
|
||||
title: 'ZH-CHAT',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: Themes.light,
|
||||
darkTheme: Themes.dark,
|
||||
initialRoute: AppRouter.transitRoute,
|
||||
unknownRoute: AppRouter.unknownRoute,
|
||||
defaultTransition: Transition.cupertino,
|
||||
getPages: AppRouter.getPages,
|
||||
builder: EasyLoading.init(),
|
||||
initialBinding: BindingsBuilder(() {
|
||||
Get.put(AuthService());
|
||||
Get.put(TabbarService());
|
||||
Get.put(TimService());
|
||||
}));
|
||||
}
|
||||
}
|
||||
31
lib/middleware/auth_middleware.dart
Normal file
31
lib/middleware/auth_middleware.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:chat/routes/app_routes.dart';
|
||||
import 'package:chat/routes/auth_routes.dart';
|
||||
import 'package:chat/services/auth_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class EnsureAuthMiddleware extends GetMiddleware {
|
||||
@override
|
||||
int? get priority => -1;
|
||||
|
||||
@override
|
||||
RouteSettings? redirect(String? route) {
|
||||
if (!AuthService.to.isUserLogin) {
|
||||
return const RouteSettings(name: AuthRoutes.index);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class EnsureNotAuthMiddleware extends GetMiddleware {
|
||||
@override
|
||||
int? get priority => -1;
|
||||
|
||||
@override
|
||||
RouteSettings? redirect(String? route) {
|
||||
if (AuthService.to.isUserLogin) {
|
||||
return const RouteSettings(name: AppRoutes.home);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
45
lib/routes/app_router.dart
Normal file
45
lib/routes/app_router.dart
Normal file
@@ -0,0 +1,45 @@
|
||||
import 'package:chat/routes/app_routes.dart';
|
||||
import 'package:chat/routes/auth_routes.dart';
|
||||
import 'package:chat/views/home/index_page.dart';
|
||||
import 'package:chat/views/public/app_page.dart';
|
||||
import 'package:chat/views/public/scan_page.dart';
|
||||
import 'package:chat/views/public/transit_page.dart';
|
||||
import 'package:chat/views/public/unknown_page.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class AppRouter {
|
||||
// 引导页
|
||||
static const String transitRoute = AppRoutes.transit;
|
||||
// 未知页面,返回主页
|
||||
static final GetPage unknownRoute = GetPage(
|
||||
name: AppRoutes.notfound,
|
||||
page: () => const UnknownPage(),
|
||||
);
|
||||
|
||||
// 路由页面
|
||||
static final List<GetPage<dynamic>> getPages = [
|
||||
/// 过渡页面
|
||||
GetPage(
|
||||
name: AppRoutes.transit,
|
||||
page: () => const TransitPage(),
|
||||
),
|
||||
|
||||
GetPage(
|
||||
name: AppRoutes.app,
|
||||
page: () => AppPage(),
|
||||
),
|
||||
|
||||
/// 首页
|
||||
GetPage(
|
||||
name: AppRoutes.home,
|
||||
page: () => const HomePage(),
|
||||
),
|
||||
|
||||
GetPage(
|
||||
name: AppRoutes.scan,
|
||||
page: () => const ScanPage(),
|
||||
),
|
||||
|
||||
AuthRoutes.router,
|
||||
];
|
||||
}
|
||||
17
lib/routes/app_routes.dart
Normal file
17
lib/routes/app_routes.dart
Normal file
@@ -0,0 +1,17 @@
|
||||
/// 这里是为了定义别名路由的名称,
|
||||
/// 具体映射关系,在app_router 的 getPages 中实现
|
||||
abstract class AppRoutes {
|
||||
/// 过渡页
|
||||
static const String transit = '/transit';
|
||||
|
||||
/// 找不到页面的时候
|
||||
static const String notfound = '/notfound';
|
||||
|
||||
/// 根页面
|
||||
static const String app = '/';
|
||||
|
||||
/// 首页
|
||||
static const String home = '/home';
|
||||
|
||||
static const String scan = '/scan';
|
||||
}
|
||||
16
lib/routes/auth_routes.dart
Normal file
16
lib/routes/auth_routes.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:chat/middleware/auth_middleware.dart';
|
||||
import 'package:chat/views/auth/index_page.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
abstract class AuthRoutes {
|
||||
/// 身份验证页面
|
||||
static const String index = '/auth';
|
||||
|
||||
static GetPage router = GetPage(
|
||||
name: AuthRoutes.index,
|
||||
middlewares: [
|
||||
EnsureNotAuthMiddleware(),
|
||||
],
|
||||
page: () => const AuthPage(),
|
||||
);
|
||||
}
|
||||
11
lib/services/auth_service.dart
Normal file
11
lib/services/auth_service.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class AuthService extends GetxService {
|
||||
static AuthService get to => Get.find<AuthService>();
|
||||
|
||||
/// 供外部使用的,判断是否登录的状态
|
||||
get isUserLogin => isLogin.value;
|
||||
|
||||
/// 登录状态记录,可监听的,这样ever才能监听到
|
||||
final RxBool isLogin = false.obs;
|
||||
}
|
||||
11
lib/services/tabbar_service.dart
Normal file
11
lib/services/tabbar_service.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class TabbarService extends GetxService {
|
||||
static TabbarService get to => Get.find<TabbarService>();
|
||||
|
||||
final RxInt _index = 0.obs;
|
||||
|
||||
set index(int value) => _index.value = value;
|
||||
|
||||
int get index => _index.value;
|
||||
}
|
||||
7
lib/services/tim_service.dart
Normal file
7
lib/services/tim_service.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class TimService extends GetxService {
|
||||
Future<TimService> init() async {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
15
lib/views/auth/index_page.dart
Normal file
15
lib/views/auth/index_page.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AuthPage extends StatefulWidget {
|
||||
const AuthPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AuthPage> createState() => _AuthPageState();
|
||||
}
|
||||
|
||||
class _AuthPageState extends State<AuthPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
15
lib/views/home/index_page.dart
Normal file
15
lib/views/home/index_page.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class HomePage extends StatefulWidget {
|
||||
const HomePage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_HomePageState createState() => _HomePageState();
|
||||
}
|
||||
|
||||
class _HomePageState extends State<HomePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
15
lib/views/moments/index/index_page.dart
Normal file
15
lib/views/moments/index/index_page.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MomentsPage extends StatefulWidget {
|
||||
const MomentsPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MomentsPageState createState() => _MomentsPageState();
|
||||
}
|
||||
|
||||
class _MomentsPageState extends State<MomentsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
78
lib/views/public/app_page.dart
Normal file
78
lib/views/public/app_page.dart
Normal file
@@ -0,0 +1,78 @@
|
||||
import 'package:chat/configs/app_colors.dart';
|
||||
import 'package:chat/services/tabbar_service.dart';
|
||||
import 'package:chat/views/home/index_page.dart';
|
||||
import 'package:chat/views/moments/index/index_page.dart';
|
||||
import 'package:chat/views/user/index/user_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:proste_indexed_stack/proste_indexed_stack.dart';
|
||||
|
||||
class AppPage extends StatelessWidget {
|
||||
AppPage({Key? key}) : super(key: key);
|
||||
|
||||
final List<IndexedStackChild> _tabBarPageList = [
|
||||
IndexedStackChild(child: const HomePage()),
|
||||
IndexedStackChild(child: const MomentsPage()),
|
||||
IndexedStackChild(child: const UserPage()),
|
||||
];
|
||||
|
||||
final List<Map> _tabBarList = [
|
||||
{
|
||||
'icon': 'tabBar_03.png',
|
||||
'label': '首页',
|
||||
},
|
||||
{
|
||||
'icon': 'tabBar_03.png',
|
||||
'label': '首页',
|
||||
},
|
||||
{
|
||||
'icon': 'tabBar_03.png',
|
||||
'label': '首页',
|
||||
},
|
||||
];
|
||||
|
||||
Widget _bottomNavigationBar() {
|
||||
return GetX<TabbarService>(
|
||||
builder: (_) {
|
||||
return BottomNavigationBar(
|
||||
currentIndex: _.index,
|
||||
onTap: (index) {
|
||||
_.index = index;
|
||||
},
|
||||
items: _tabBarList.map((item) {
|
||||
return BottomNavigationBarItem(
|
||||
icon: Image.asset(
|
||||
'assets/icons/${item['icon']}',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
activeIcon: Image.asset(
|
||||
'assets/icons/${item['icon']}',
|
||||
color: AppColors.primary,
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
label: item['label'],
|
||||
tooltip: '',
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: GetX<TabbarService>(
|
||||
builder: (_) {
|
||||
return ProsteIndexedStack(
|
||||
index: _.index,
|
||||
children: _tabBarPageList,
|
||||
);
|
||||
},
|
||||
),
|
||||
bottomNavigationBar: _bottomNavigationBar(),
|
||||
);
|
||||
}
|
||||
}
|
||||
15
lib/views/public/scan_page.dart
Normal file
15
lib/views/public/scan_page.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ScanPage extends StatefulWidget {
|
||||
const ScanPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ScanPageState createState() => _ScanPageState();
|
||||
}
|
||||
|
||||
class _ScanPageState extends State<ScanPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
73
lib/views/public/transit_page.dart
Normal file
73
lib/views/public/transit_page.dart
Normal file
@@ -0,0 +1,73 @@
|
||||
import 'dart:async';
|
||||
import 'package:chat/routes/app_routes.dart';
|
||||
import 'package:chat/routes/auth_routes.dart';
|
||||
import 'package:chat/services/auth_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class TransitPage extends StatefulWidget {
|
||||
const TransitPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<TransitPage> createState() => _TransitPageState();
|
||||
}
|
||||
|
||||
/// 这里的加载图片,应该是可以请求网络图片的,但是要考虑网络图片的加载周期,还有网络环境因素等
|
||||
class _TransitPageState extends State<TransitPage> {
|
||||
final int _leftTime = 5;
|
||||
late Timer _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void _jumpToRootPage() {
|
||||
if (AuthService.to.isUserLogin) {
|
||||
Get.offAllNamed(AppRoutes.app);
|
||||
} else {
|
||||
Get.offAllNamed(AuthRoutes.index);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: Swiper(
|
||||
autoplay: true,
|
||||
itemCount: 2,
|
||||
pagination: const SwiperPagination(),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Image.asset(
|
||||
'assets/transits/${index + 1}.png',
|
||||
fit: BoxFit.cover,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 32,
|
||||
right: 32,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
_timer.cancel();
|
||||
_jumpToRootPage();
|
||||
},
|
||||
child: Text(
|
||||
'跳过($_leftTime)',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
20
lib/views/public/unknown_page.dart
Normal file
20
lib/views/public/unknown_page.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class UnknownPage extends StatelessWidget {
|
||||
const UnknownPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
child: const Text('未知的页面'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
15
lib/views/user/index/user_page.dart
Normal file
15
lib/views/user/index/user_page.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class UserPage extends StatefulWidget {
|
||||
const UserPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_UserPageState createState() => _UserPageState();
|
||||
}
|
||||
|
||||
class _UserPageState extends State<UserPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
52
lib/widgets/custom_avatar.dart
Normal file
52
lib/widgets/custom_avatar.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class CustomAvatar extends StatelessWidget {
|
||||
String? avtarUrl;
|
||||
double size;
|
||||
double radius;
|
||||
|
||||
CustomAvatar(
|
||||
this.avtarUrl, {
|
||||
Key? key,
|
||||
this.size = 44,
|
||||
this.radius = 4,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (avtarUrl == null || avtarUrl == '') {
|
||||
avtarUrl = 'assets/chats/default_avatar.png';
|
||||
}
|
||||
|
||||
avtarUrl = avtarUrl!.trim();
|
||||
|
||||
return SizedBox(
|
||||
width: size,
|
||||
height: size,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(radius),
|
||||
child: _image(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _image() {
|
||||
if (avtarUrl!.contains('http') || avtarUrl!.contains('https')) {
|
||||
return CachedNetworkImage(
|
||||
imageUrl: avtarUrl!,
|
||||
width: size,
|
||||
height: size,
|
||||
fit: BoxFit.cover,
|
||||
);
|
||||
} else {
|
||||
return Image.asset(
|
||||
avtarUrl!,
|
||||
width: size,
|
||||
height: size,
|
||||
fit: BoxFit.cover,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
lib/widgets/custom_circle_avatar.dart
Normal file
62
lib/widgets/custom_circle_avatar.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:chat/configs/app_colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class CustomCircleAvatar extends StatelessWidget {
|
||||
String? avtarUrl;
|
||||
double size;
|
||||
Color borderColor;
|
||||
double borderWidth;
|
||||
|
||||
CustomCircleAvatar(
|
||||
this.avtarUrl, {
|
||||
Key? key,
|
||||
this.size = 44,
|
||||
this.borderColor = AppColors.transparent,
|
||||
this.borderWidth = 2,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (avtarUrl == null || avtarUrl == '') {
|
||||
avtarUrl = 'assets/chats/default_avatar.png';
|
||||
}
|
||||
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(size / 2),
|
||||
border: Border.all(
|
||||
color: borderColor,
|
||||
width: borderWidth,
|
||||
),
|
||||
),
|
||||
child: PhysicalModel(
|
||||
color: borderColor.withOpacity(0.1),
|
||||
shape: BoxShape.circle,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: _image(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _image() {
|
||||
if (avtarUrl!.contains('http')) {
|
||||
return CachedNetworkImage(
|
||||
imageUrl: avtarUrl!,
|
||||
width: size,
|
||||
height: size,
|
||||
fit: BoxFit.cover,
|
||||
);
|
||||
} else {
|
||||
return Image.asset(
|
||||
avtarUrl!,
|
||||
width: size,
|
||||
height: size,
|
||||
fit: BoxFit.cover,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
lib/widgets/custom_easy_refresh.dart
Normal file
89
lib/widgets/custom_easy_refresh.dart
Normal file
@@ -0,0 +1,89 @@
|
||||
import 'package:chat/configs/app_colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
|
||||
class CustomEasyRefresh {
|
||||
static Header get header => ClassicalHeader(
|
||||
refreshText: '下拉刷新',
|
||||
refreshReadyText: '松开刷新',
|
||||
refreshingText: '刷新中...',
|
||||
refreshedText: '刷新完成',
|
||||
infoText: '上次更新 %T',
|
||||
infoColor: AppColors.primary,
|
||||
textColor: AppColors.primary,
|
||||
);
|
||||
|
||||
static Footer get ballFooter => BallPulseFooter(
|
||||
color: AppColors.primary,
|
||||
);
|
||||
|
||||
static Footer get footer => ClassicalFooter(
|
||||
loadText: '上拉加载',
|
||||
loadReadyText: '松开加载',
|
||||
loadingText: '加载中...',
|
||||
loadedText: '加载完成',
|
||||
infoText: '上次更新 %T',
|
||||
noMoreText: '没有更多了',
|
||||
infoColor: AppColors.primary,
|
||||
textColor: AppColors.primary,
|
||||
);
|
||||
|
||||
/// 数据为空的时候显示
|
||||
static Widget empty({
|
||||
String text = '暂无数据',
|
||||
double size = 156.0,
|
||||
}) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/empty.png',
|
||||
width: size,
|
||||
),
|
||||
Text(
|
||||
text,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColors.unactive,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
static Widget get first => Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
blurStyle: BlurStyle.outer,
|
||||
color: AppColors.shadow,
|
||||
blurRadius: 4,
|
||||
),
|
||||
],
|
||||
),
|
||||
width: 120,
|
||||
height: 120,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: const <Widget>[
|
||||
SpinKitFadingCircle(
|
||||
color: AppColors.primary,
|
||||
size: 50.0,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Text('加载中...'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
61
lib/widgets/custom_primary_button.dart
Normal file
61
lib/widgets/custom_primary_button.dart
Normal file
@@ -0,0 +1,61 @@
|
||||
import 'package:chat/configs/app_colors.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomPrimaryButton extends StatelessWidget {
|
||||
final VoidCallback? onPressed;
|
||||
final String text;
|
||||
final double padding;
|
||||
|
||||
const CustomPrimaryButton({
|
||||
Key? key,
|
||||
required this.text,
|
||||
this.onPressed,
|
||||
this.padding = 0,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: onPressed,
|
||||
style: ButtonStyle(
|
||||
padding: MaterialStateProperty.resolveWith(
|
||||
(states) {
|
||||
return EdgeInsets.all(padding);
|
||||
},
|
||||
),
|
||||
shape: MaterialStateProperty.all(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
),
|
||||
),
|
||||
backgroundColor: MaterialStateProperty.resolveWith(
|
||||
(states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
return AppColors.primary.withAlpha(128);
|
||||
} else {
|
||||
return AppColors.primary;
|
||||
}
|
||||
},
|
||||
),
|
||||
foregroundColor: MaterialStateProperty.resolveWith(
|
||||
(states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
return AppColors.white;
|
||||
} else {
|
||||
return AppColors.white;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
text,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user