Compare commits
56 Commits
master
...
lirongchua
| Author | SHA1 | Date |
|---|---|---|
|
|
91923e2158 | 2 years ago |
|
|
e6b807c436 | 2 years ago |
|
|
35b44f5a8c | 2 years ago |
|
|
fc5bd8c75e | 2 years ago |
|
|
c9c53a1b0f | 2 years ago |
|
|
a8536a4fb8 | 2 years ago |
|
|
5ea16ba66d | 2 years ago |
|
|
116a64eca8 | 2 years ago |
|
|
754fe15345 | 2 years ago |
|
|
f73012a33d | 2 years ago |
|
|
52fc643883 | 2 years ago |
|
|
79d5b797e0 | 2 years ago |
|
|
bce690e0b3 | 2 years ago |
|
|
4ee436ea9d | 2 years ago |
|
|
a2a04d7a56 | 2 years ago |
|
|
1e10b1aba7 | 2 years ago |
|
|
b2d0dbbe36 | 2 years ago |
|
|
cf20a313b3 | 2 years ago |
|
|
40f341da5e | 2 years ago |
|
|
9d0963aa43 | 2 years ago |
|
|
d68970bdcc | 2 years ago |
|
|
3a38ab0c72 | 2 years ago |
|
|
7a95b29eb5 | 2 years ago |
|
|
9abe619843 | 2 years ago |
|
|
6d2ad8182b | 2 years ago |
|
|
b7f39dab8d | 2 years ago |
|
|
3caa8daadf | 2 years ago |
|
|
bd8ea17214 | 2 years ago |
|
|
6821622f48 | 2 years ago |
|
|
944c25577b | 2 years ago |
|
|
87aea3bbd1 | 2 years ago |
|
|
02ca0e5c2a | 2 years ago |
|
|
63c0f98356 | 2 years ago |
|
|
08a925426e | 2 years ago |
|
|
dbd4878087 | 2 years ago |
|
|
64e0cb7872 | 2 years ago |
|
|
ddf2aa6ff8 | 2 years ago |
|
|
bf8753c22e | 2 years ago |
|
|
bb7f3afd97 | 2 years ago |
|
|
40fac61eba | 2 years ago |
|
|
790f5f046a | 2 years ago |
|
|
e9e887b900 | 2 years ago |
|
|
1a51f9c008 | 2 years ago |
|
|
5dd780eb97 | 2 years ago |
|
|
7c6ccefc15 | 2 years ago |
|
|
4983638625 | 2 years ago |
|
|
69312c16c2 | 2 years ago |
|
|
f8ce4b819c | 2 years ago |
|
|
1e0f12d682 | 2 years ago |
|
|
9e9f469bee | 2 years ago |
|
|
91450f8f58 | 2 years ago |
|
|
f0fd62bd98 | 2 years ago |
|
|
9f67ba870b | 2 years ago |
|
|
a27acb6d68 | 2 years ago |
|
|
b98627c0c1 | 2 years ago |
|
|
590e19a3ae | 2 years ago |
@ -0,0 +1,54 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
**/.history
|
||||
**/.svn/
|
||||
**/migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
**/.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
**/vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/src/timemanagerapp/.*
|
||||
**/doc/api/
|
||||
**/build/
|
||||
**/ios/
|
||||
**/linux/
|
||||
**/macos/
|
||||
**/web/
|
||||
**/windows/
|
||||
**/android/
|
||||
**/.dart_tool/
|
||||
**/.flutter-plugins
|
||||
**/.flutter-plugins-dependencies
|
||||
**/.packages
|
||||
**/.pub-cache/
|
||||
**/.pub/
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
|
||||
!.gitignore
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 372 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 192 KiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.9 MiB |
@ -1,134 +0,0 @@
|
||||
/*
|
||||
Navicat MySQL Data Transfer
|
||||
|
||||
Source Server : LRC_debian
|
||||
Source Server Version : 50742
|
||||
Source Host : 5902e9v900.zicp.fun:33006
|
||||
Source Database : expressFrame02
|
||||
|
||||
Target Server Type : MYSQL
|
||||
Target Server Version : 50742
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 2023-10-26 12:49:35
|
||||
*/
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for clocks
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `clocks`;
|
||||
CREATE TABLE `clocks` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`clockId` bigint(20) NOT NULL,
|
||||
`userId` bigint(20) NOT NULL,
|
||||
`text` text,
|
||||
`img` text,
|
||||
`music` text,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `fk_clocks_clocks_1` (`userId`),
|
||||
CONSTRAINT `fk_clocks_clocks_1` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for course
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `course`;
|
||||
CREATE TABLE `course` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`userId` bigint(20) DEFAULT NULL,
|
||||
`courseId` bigint(20) NOT NULL,
|
||||
`name` text NOT NULL,
|
||||
`credit` double DEFAULT NULL,
|
||||
`teacher` text,
|
||||
`location` text,
|
||||
`remark` text,
|
||||
`startTime` text NOT NULL,
|
||||
`endTime` text NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `fk_course_course_1` (`userId`),
|
||||
CONSTRAINT `fk_course_course_1` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for tasks
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `tasks`;
|
||||
CREATE TABLE `tasks` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`taskId` bigint(20) NOT NULL,
|
||||
`userId` bigint(20) NOT NULL,
|
||||
`content` text,
|
||||
`name` text NOT NULL,
|
||||
`startTime` text NOT NULL,
|
||||
`endTime` text NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `fk_tasks_tasks_1` (`userId`),
|
||||
CONSTRAINT `fk_tasks_tasks_1` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for teams
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `teams`;
|
||||
CREATE TABLE `teams` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`leaderId` bigint(20) NOT NULL,
|
||||
`teamName` varchar(200) NOT NULL,
|
||||
`maxNumber` bigint(20) DEFAULT NULL,
|
||||
`introduce` text,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `teamName` (`teamName`) USING BTREE,
|
||||
KEY `fk_teams_teams_1` (`leaderId`),
|
||||
CONSTRAINT `fk_teams_teams_1` FOREIGN KEY (`leaderId`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for users
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `users`;
|
||||
CREATE TABLE `users` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`username` varchar(255) NOT NULL,
|
||||
`password` text NOT NULL,
|
||||
`role` bigint(20) NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `username` (`username`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for userteams
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `userteams`;
|
||||
CREATE TABLE `userteams` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`userId` bigint(20) NOT NULL,
|
||||
`teamId` bigint(20) NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `fk_userteams_userteams_1` (`userId`),
|
||||
KEY `fk_userteams_userteams_2` (`teamId`),
|
||||
CONSTRAINT `fk_userteams_userteams_1` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_userteams_userteams_2` FOREIGN KEY (`teamId`) REFERENCES `teams` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for works
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `works`;
|
||||
CREATE TABLE `works` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`userId` bigint(20) NOT NULL,
|
||||
`workId` bigint(20) NOT NULL,
|
||||
`teamId` bigint(20) NOT NULL,
|
||||
`name` text NOT NULL,
|
||||
`content` text,
|
||||
`status` text,
|
||||
`endTime` text NOT NULL,
|
||||
`startTime` text NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `fk_works_works_1` (`userId`),
|
||||
KEY `fk_works_works_2` (`teamId`),
|
||||
CONSTRAINT `fk_works_works_1` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_works_works_2` FOREIGN KEY (`teamId`) REFERENCES `teams` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
|
||||
|
Before Width: | Height: | Size: 243 KiB |
|
Before Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 1.0 MiB |
@ -1,133 +1,133 @@
|
||||
// import 'package:timemanagerapp/entity/ScheduleForm.dart';
|
||||
//
|
||||
// import '../database/dao/WorkDao.dart';
|
||||
// import '../entity/Work.dart';
|
||||
// import '../setting/Setting.dart';
|
||||
// import '../util/dataUtil.dart';
|
||||
// import 'NetWorkController.dart';
|
||||
//
|
||||
// class WorkController {
|
||||
// static IdGenerator idGenerator = IdGenerator();
|
||||
// static List<Work> WorkList = []; //实时维护的courseList缓存
|
||||
// static NetWorkController netWorkController = NetWorkController();
|
||||
//
|
||||
// DateTime termstartdate = Setting.startdate; //Setting.getStartDate();
|
||||
//
|
||||
// Future<List<Work>> getWorks() async {
|
||||
// //todo http获取
|
||||
// List<Map<String, dynamic>> workMaps = await WorkDao().getWorks();
|
||||
// List<Work> Works = []; // 用于存储转换后的Work对象列表
|
||||
//
|
||||
// for (var workMap in workMaps) {
|
||||
// // 使用Work类的构造函数从Map创建Work对象
|
||||
// Work work = Work(
|
||||
// id: workMap['id'],
|
||||
// userId: workMap['userId'],
|
||||
// content: workMap['content'],
|
||||
// workId: workMap['workId'],
|
||||
// name: workMap['name'],
|
||||
// startTime: DateTime.parse(workMap['startTime']),
|
||||
// endTime: DateTime.parse(workMap['endTime']),
|
||||
// status: workMap['status'],
|
||||
// teamId: workMap['teamId'],
|
||||
// );
|
||||
// Works.add(work);
|
||||
// }
|
||||
// WorkList = Works; // 将Work对象添加到列表中
|
||||
// return WorkList;
|
||||
// }
|
||||
//
|
||||
// //addscheduleForm
|
||||
// Future<void> addScheduleForm(ScheduleForm scheduleForm,int teamId) async {
|
||||
// List<Work> WorkListToInsert = [];
|
||||
// int allWorkId = await idGenerator.generateId();
|
||||
// for (int week = scheduleForm.getStartWeek; week <= scheduleForm.getEndWeek; week++) {
|
||||
// for (int day in scheduleForm.selectedDays) {
|
||||
// // 计算具体的日期和时间
|
||||
// final startDate = termstartdate.add(Duration(
|
||||
// days: (7 * (week - 1) + day! - 1),
|
||||
// hours: scheduleForm.getStartTime.hour,
|
||||
// minutes: scheduleForm.getStartTime.minute
|
||||
// ));
|
||||
//
|
||||
// final endDate = termstartdate.add(Duration(
|
||||
// days: (7 * (week - 1) + day! - 1),
|
||||
// hours: scheduleForm.getEndTime.hour,
|
||||
// minutes: scheduleForm.getEndTime.minute,
|
||||
// ));
|
||||
// Work work = Work(
|
||||
// id: await idGenerator.generateId(),
|
||||
// name: scheduleForm.getName,
|
||||
// workId: allWorkId,
|
||||
// userId: Setting.user!.getId!,
|
||||
// status: "未完成",
|
||||
// content: scheduleForm.getContent,
|
||||
// teamId: teamId,
|
||||
// endTime: endDate,
|
||||
// startTime: startDate,
|
||||
// );
|
||||
// WorkListToInsert.add(work);
|
||||
// }
|
||||
// }
|
||||
// await insertWorkList(WorkListToInsert);
|
||||
// }
|
||||
//
|
||||
// Future<int> insertWork(Work Work) async {
|
||||
// return await WorkDao().insertWork(Work);
|
||||
// }
|
||||
//
|
||||
// Future<int> insertWorkList(List<Work> workList) async {
|
||||
// int result = 0;
|
||||
// for (Work work in workList) {
|
||||
// result += await WorkDao().insertWork(work);
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// //模仿Task的数数据操作写work
|
||||
// //query
|
||||
// Future<List<Work>> getWorkList() async {
|
||||
// List<Map<String, dynamic>> workMaps = await WorkDao().getWorks();
|
||||
// List<Work> workList = []; // 用于存储转换后的Work对象列表
|
||||
//
|
||||
// for (var workMap in workMaps) {
|
||||
// // 使用Work类的构造函数从Map创建Work对象
|
||||
// Work work = Work(
|
||||
// id: workMap['id'],
|
||||
// userId: workMap['userId'],
|
||||
// content: workMap['content'],
|
||||
// workId: workMap['workId'],
|
||||
// name: workMap['name'],
|
||||
// startTime: DateTime.parse(workMap['startTime']),
|
||||
// endTime: DateTime.parse(workMap['endTime']),
|
||||
// status: workMap['status'],
|
||||
// teamId: workMap['teamId'],
|
||||
// );
|
||||
// workList.add(work);
|
||||
// }
|
||||
// WorkList = workList; // 将Work对象添加到列表中
|
||||
// return WorkList;
|
||||
// }
|
||||
//
|
||||
// // //delete 模仿Task的数数据操作
|
||||
// // Future<int> deleteWorkByid(int id) async{
|
||||
// // return await WorkDao().deleteWorkByid(id);
|
||||
// // }
|
||||
//
|
||||
//
|
||||
// Future<int> deleteWorkByWorkid(int workid) async {
|
||||
// return await WorkDao().deleteWorkByWorkid(workid);
|
||||
// }
|
||||
//
|
||||
// Future<int> deleteAllWorks() async {
|
||||
// return await WorkDao().deleteAllWorks();
|
||||
// }
|
||||
//
|
||||
// //update
|
||||
// Future<int> updateWork(Work work) async {
|
||||
// return await WorkDao().updateWork(work);
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// }
|
||||
import 'package:timemanagerapp/entity/ScheduleForm.dart';
|
||||
|
||||
import '../database/dao/WorkDao.dart';
|
||||
import '../entity/Work.dart';
|
||||
import '../setting/Setting.dart';
|
||||
import '../util/dataUtil.dart';
|
||||
import 'NetWorkController.dart';
|
||||
|
||||
class WorkController {
|
||||
static IdGenerator idGenerator = IdGenerator();
|
||||
static List<Work> WorkList = []; //实时维护的courseList缓存
|
||||
static NetWorkController netWorkController = NetWorkController();
|
||||
|
||||
DateTime termstartdate = Setting.startdate; //Setting.getStartDate();
|
||||
|
||||
Future<List<Work>> getWorks() async {
|
||||
//todo http获取
|
||||
List<Map<String, dynamic>> workMaps = await WorkDao().getWorks();
|
||||
List<Work> Works = []; // 用于存储转换后的Work对象列表
|
||||
|
||||
for (var workMap in workMaps) {
|
||||
// 使用Work类的构造函数从Map创建Work对象
|
||||
Work work = Work(
|
||||
id: workMap['id'],
|
||||
userId: workMap['userId'],
|
||||
content: workMap['content'],
|
||||
workId: workMap['workId'],
|
||||
name: workMap['name'],
|
||||
startTime: DateTime.parse(workMap['startTime']),
|
||||
endTime: DateTime.parse(workMap['endTime']),
|
||||
status: workMap['status'],
|
||||
teamId: workMap['teamId'],
|
||||
);
|
||||
Works.add(work);
|
||||
}
|
||||
WorkList = Works; // 将Work对象添加到列表中
|
||||
return WorkList;
|
||||
}
|
||||
|
||||
//addscheduleForm
|
||||
Future<void> addScheduleForm(ScheduleForm scheduleForm,int teamId) async {
|
||||
List<Work> WorkListToInsert = [];
|
||||
int allWorkId = await idGenerator.generateId();
|
||||
for (int week = scheduleForm.getStartWeek; week <= scheduleForm.getEndWeek; week++) {
|
||||
for (int day in scheduleForm.selectedDays) {
|
||||
// 计算具体的日期和时间
|
||||
final startDate = termstartdate.add(Duration(
|
||||
days: (7 * (week - 1) + day! - 1),
|
||||
hours: scheduleForm.getStartTime.hour,
|
||||
minutes: scheduleForm.getStartTime.minute
|
||||
));
|
||||
|
||||
final endDate = termstartdate.add(Duration(
|
||||
days: (7 * (week - 1) + day! - 1),
|
||||
hours: scheduleForm.getEndTime.hour,
|
||||
minutes: scheduleForm.getEndTime.minute,
|
||||
));
|
||||
Work work = Work(
|
||||
id: await idGenerator.generateId(),
|
||||
name: scheduleForm.getName,
|
||||
workId: allWorkId,
|
||||
userId: Setting.user!.getId!,
|
||||
status: "未完成",
|
||||
content: scheduleForm.getContent,
|
||||
teamId: teamId,
|
||||
endTime: endDate,
|
||||
startTime: startDate,
|
||||
);
|
||||
WorkListToInsert.add(work);
|
||||
}
|
||||
}
|
||||
await insertWorkList(WorkListToInsert);
|
||||
}
|
||||
|
||||
Future<int> insertWork(Work Work) async {
|
||||
return await WorkDao().insertWork(Work);
|
||||
}
|
||||
|
||||
Future<int> insertWorkList(List<Work> workList) async {
|
||||
int result = 0;
|
||||
for (Work work in workList) {
|
||||
result += await WorkDao().insertWork(work);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//模仿Task的数数据操作写work
|
||||
//query
|
||||
Future<List<Work>> getWorkList() async {
|
||||
List<Map<String, dynamic>> workMaps = await WorkDao().getWorks();
|
||||
List<Work> workList = []; // 用于存储转换后的Work对象列表
|
||||
|
||||
for (var workMap in workMaps) {
|
||||
// 使用Work类的构造函数从Map创建Work对象
|
||||
Work work = Work(
|
||||
id: workMap['id'],
|
||||
userId: workMap['userId'],
|
||||
content: workMap['content'],
|
||||
workId: workMap['workId'],
|
||||
name: workMap['name'],
|
||||
startTime: DateTime.parse(workMap['startTime']),
|
||||
endTime: DateTime.parse(workMap['endTime']),
|
||||
status: workMap['status'],
|
||||
teamId: workMap['teamId'],
|
||||
);
|
||||
workList.add(work);
|
||||
}
|
||||
WorkList = workList; // 将Work对象添加到列表中
|
||||
return WorkList;
|
||||
}
|
||||
|
||||
// //delete 模仿Task的数数据操作
|
||||
// Future<int> deleteWorkByid(int id) async{
|
||||
// return await WorkDao().deleteWorkByid(id);
|
||||
// }
|
||||
|
||||
|
||||
Future<int> deleteWorkByWorkid(int workid) async {
|
||||
return await WorkDao().deleteWorkByWorkid(workid);
|
||||
}
|
||||
|
||||
Future<int> deleteAllWorks() async {
|
||||
return await WorkDao().deleteAllWorks();
|
||||
}
|
||||
|
||||
//update
|
||||
Future<int> updateWork(Work work) async {
|
||||
return await WorkDao().updateWork(work);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
class FreeTime {
|
||||
int? id;
|
||||
int? userId;
|
||||
String? content;
|
||||
String? name;
|
||||
DateTime startTime;
|
||||
DateTime endTime;
|
||||
|
||||
FreeTime({
|
||||
this.id,
|
||||
this.userId,
|
||||
this.content,
|
||||
this.name,
|
||||
required this.startTime,
|
||||
required this.endTime,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'userId': userId,
|
||||
'content': "$content",
|
||||
'name': "$name",
|
||||
'startTime': "${startTime.toIso8601String()}",
|
||||
'endTime': "${endTime.toIso8601String()}"
|
||||
};
|
||||
}
|
||||
|
||||
factory FreeTime.fromJson(Map<String, dynamic> task) {
|
||||
return FreeTime(
|
||||
// id: task['id'],
|
||||
// userId: task['userId'],
|
||||
// content: task['content'],
|
||||
// name: task['name'],
|
||||
startTime: DateTime.parse(task['startTime']),
|
||||
endTime: DateTime.parse(task['endTime']),
|
||||
);
|
||||
}
|
||||
|
||||
// Getter methods
|
||||
int? get getId => id;
|
||||
|
||||
int? get getUserId => userId;
|
||||
|
||||
String? get getContent => content;
|
||||
|
||||
String? get getName => name;
|
||||
|
||||
DateTime get getStartTime => startTime;
|
||||
|
||||
DateTime get getEndTime => endTime;
|
||||
|
||||
// Setter methods
|
||||
set setId(int newId) {
|
||||
id = newId;
|
||||
}
|
||||
|
||||
set setUserId(int newUserId) {
|
||||
userId = newUserId;
|
||||
}
|
||||
|
||||
set setContent(String newContent) {
|
||||
content = newContent;
|
||||
}
|
||||
|
||||
set setName(String newName) {
|
||||
name = newName;
|
||||
}
|
||||
|
||||
set setStartTime(DateTime newStartTime) {
|
||||
startTime = newStartTime;
|
||||
}
|
||||
|
||||
set setEndTime(DateTime newEndTime) {
|
||||
endTime = newEndTime;
|
||||
}
|
||||
|
||||
// toString method
|
||||
@override
|
||||
String toString() {
|
||||
return 'FreeTime(id: $id, userId: $userId, content: $content, name: $name, startTime: $startTime, endTime: $endTime)';
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,17 @@
|
||||
// import 'package:flutter/cupertino.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
//
|
||||
// import '../widgets/ManageUserTeamWidget.dart';
|
||||
//
|
||||
// class ManageUserTeamRoute extends StatelessWidget {
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// appBar: AppBar(
|
||||
// title: Text('团队成员管理'),
|
||||
// ),
|
||||
// // body: ManageUserTeamWidget(),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../widgets/ManageUserTeamWidget.dart';
|
||||
|
||||
class ManageUserTeamRoute extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('团队成员管理'),
|
||||
),
|
||||
// body: ManageUserTeamWidget(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,38 +1,38 @@
|
||||
// import 'dart:developer';
|
||||
//
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:shared_preferences/shared_preferences.dart';
|
||||
// import 'package:timemanagerapp/setting/Setting.dart';
|
||||
// import 'package:timemanagerapp/util/GetCourseByLogin.dart';
|
||||
// import 'package:timemanagerapp/widgets/AddCourseFormWidget.dart';
|
||||
// import 'package:timemanagerapp/widgets/LoginWidget.dart';
|
||||
// import 'package:timemanagerapp/widgets/TimetableWidget.dart';
|
||||
//
|
||||
//
|
||||
// init() async {
|
||||
// WidgetsFlutterBinding.ensureInitialized();
|
||||
// await Setting.init();
|
||||
// }
|
||||
//
|
||||
// void main() async {
|
||||
// await init();
|
||||
// runApp(MyApp());
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// class MyApp extends StatelessWidget {
|
||||
//
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return MaterialApp(
|
||||
// home: Scaffold(
|
||||
// appBar: AppBar(
|
||||
// title: Text('课表'),
|
||||
// ),
|
||||
// body: TimetableWidget(),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:timemanagerapp/setting/Setting.dart';
|
||||
import 'package:timemanagerapp/util/GetCourseByLogin.dart';
|
||||
import 'package:timemanagerapp/widgets/AddCourseFormWidget.dart';
|
||||
import 'package:timemanagerapp/widgets/LoginWidget.dart';
|
||||
import 'package:timemanagerapp/widgets/TimetableWidget.dart';
|
||||
|
||||
|
||||
init() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await Setting.init();
|
||||
}
|
||||
|
||||
void main() async {
|
||||
await init();
|
||||
runApp(MyApp());
|
||||
|
||||
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('课表'),
|
||||
),
|
||||
body: TimetableWidget(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,132 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:logger/src/logger.dart';
|
||||
import 'package:logger/src/log_output.dart';
|
||||
import 'dart:io' as io;
|
||||
|
||||
class MyLogger extends StatefulWidget {
|
||||
@override
|
||||
_MyLoggerState createState() => _MyLoggerState();
|
||||
}
|
||||
|
||||
class _MyLoggerState extends State<MyLogger> {
|
||||
late File file;
|
||||
late Logger logger;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
getDirectoryForLogRecord().whenComplete(
|
||||
() {
|
||||
FileOutput fileOutPut = FileOutput(file: file);
|
||||
ConsoleOutput consoleOutput = ConsoleOutput();
|
||||
List<LogOutput> multiOutput = [fileOutPut, consoleOutput];
|
||||
logger = Logger(
|
||||
filter: DevelopmentFilter(),
|
||||
// Use the default LogFilter (-> only log in debug mode)
|
||||
printer: PrettyPrinter(
|
||||
methodCount: 2,
|
||||
// number of method calls to be displayed
|
||||
errorMethodCount: 8,
|
||||
// number of method calls if stacktrace is provided
|
||||
lineLength: 120,
|
||||
// width of the output
|
||||
colors: false,
|
||||
// Colorful log messages
|
||||
printEmojis: true,
|
||||
// Print an emoji for each log message
|
||||
printTime: true // Should each log print contain a timestamp
|
||||
),
|
||||
// Use the PrettyPrinter to format and print log
|
||||
output:
|
||||
MultiOutput(multiOutput) // Use the default LogOutput (-> send everything to console)
|
||||
);
|
||||
},
|
||||
);
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Future<void> getDirectoryForLogRecord() async {
|
||||
final Directory directory = await getApplicationDocumentsDirectory();
|
||||
file = File('${directory.path}/withMultiOutput.txt');
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ElevatedButton(
|
||||
onPressed: () {
|
||||
print("you pressed it");
|
||||
// logger.v("Verbose log");
|
||||
//
|
||||
// logger.d("Debug log");
|
||||
//
|
||||
// logger.i("Info log");
|
||||
//
|
||||
// logger.w("Warning log");
|
||||
//
|
||||
// logger.e("Error log");
|
||||
//
|
||||
// logger.wtf("What a terrible failure log");
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
|
||||
String content = file.readAsStringSync();
|
||||
return AlertDialog(
|
||||
title: Text('结果'),
|
||||
content: SingleChildScrollView(
|
||||
child: Text(content)),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
// height: 60,
|
||||
// minWidth: 120,
|
||||
// color: Colors.blue,
|
||||
child: Text(
|
||||
'TEST WITH BOTH',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes the log output to a file.
|
||||
class FileOutput extends LogOutput {
|
||||
late File file;
|
||||
final bool overrideExisting;
|
||||
final Encoding encoding;
|
||||
IOSink ? _sink;
|
||||
|
||||
// IOSink? _sink;
|
||||
|
||||
FileOutput({
|
||||
required this.file,
|
||||
this.overrideExisting = false,
|
||||
this.encoding = utf8,
|
||||
});
|
||||
|
||||
@override
|
||||
void init() {
|
||||
_sink = file.openWrite(
|
||||
mode: overrideExisting ? FileMode.writeOnly : FileMode.writeOnlyAppend,
|
||||
encoding: encoding,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void output(OutputEvent event) {
|
||||
_sink?.writeAll(event.lines, '\n');
|
||||
print('log-------'+event.lines.toString()+'\n');
|
||||
}
|
||||
|
||||
@override
|
||||
void destroy() async {
|
||||
await _sink?.flush();
|
||||
await _sink?.close();
|
||||
}
|
||||
}
|
||||
@ -1,135 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:timemanagerapp/controller/UserController.dart';
|
||||
import 'package:timemanagerapp/setting/Setting.dart';
|
||||
|
||||
import '../entity/User.dart';
|
||||
|
||||
class ChangeUserWidget extends StatefulWidget {
|
||||
@override
|
||||
_ChangeUserWidgetState createState() => _ChangeUserWidgetState();
|
||||
}
|
||||
|
||||
class _ChangeUserWidgetState extends State<ChangeUserWidget> {
|
||||
UserController userController = UserController.getInstance();
|
||||
|
||||
final TextEditingController usernameController = TextEditingController();
|
||||
final TextEditingController passwordController = TextEditingController();
|
||||
final TextEditingController confirmPasswordController = TextEditingController();
|
||||
|
||||
Future<void> handleRegister(context) async {
|
||||
String username = usernameController.text;
|
||||
String password = passwordController.text;
|
||||
String confirmPassword = confirmPasswordController.text;
|
||||
|
||||
|
||||
//密码不能为空
|
||||
if (password == '' || confirmPassword == '') {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('结果'),
|
||||
content: Text('密码不能为空'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // 关闭对话框
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
return;
|
||||
}else if (password != confirmPassword) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('结果'),
|
||||
content: Text('两次输入的密码不一致'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // 关闭对话框
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
return;
|
||||
}else{
|
||||
bool res = await userController.updateUser(User(id:Setting.user!.getId!,username:username, password:password, role:0));
|
||||
if(res){
|
||||
Navigator.pop(context);
|
||||
}else{
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('结果'),
|
||||
content: Text('修改失败'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // 关闭对话框
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('修改帐户'),
|
||||
),
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
controller: usernameController,
|
||||
decoration: InputDecoration(
|
||||
labelText: '用户名',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.0),
|
||||
TextFormField(
|
||||
controller: passwordController,
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: '密码',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.0),
|
||||
TextFormField(
|
||||
controller: confirmPasswordController,
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: '确认密码',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24.0),
|
||||
ElevatedButton(
|
||||
onPressed:()=> handleRegister(context),
|
||||
child: Text('提交'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:timemanagerapp/controller/TeamController.dart';
|
||||
import 'package:timemanagerapp/entity/Team.dart';
|
||||
|
||||
import '../setting/Setting.dart';
|
||||
|
||||
class JoinTeamWidget extends StatefulWidget {
|
||||
const JoinTeamWidget({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_JoinTeamWidgetState createState() => _JoinTeamWidgetState();
|
||||
}
|
||||
|
||||
class _JoinTeamWidgetState extends State<JoinTeamWidget> {
|
||||
TeamController teamController = TeamController();
|
||||
|
||||
TextEditingController teamNameController = TextEditingController();
|
||||
// TextEditingController teamDescriptionController = TextEditingController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('加入团队'),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
TextField(
|
||||
controller: teamNameController,
|
||||
decoration: InputDecoration(
|
||||
labelText: '团队名称',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
// TextField(
|
||||
// controller: teamDescriptionController,
|
||||
// decoration: InputDecoration(
|
||||
// labelText: '团队描述',
|
||||
// ),
|
||||
// ),
|
||||
SizedBox(height: 20),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
String teamName = teamNameController.text;
|
||||
// String teamDescription = teamDescriptionController.text;
|
||||
|
||||
bool res = await teamController.joinTeam(teamName);
|
||||
if(res==false){
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('结果'),
|
||||
content: Text('团队不存在或已加入'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // 关闭对话框
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}else{
|
||||
Setting.teamWidgetKey!.currentState!.futureDo();
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
child: Text('确定'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/**
|
||||
* @desc 分割线
|
||||
* @author xiedong
|
||||
* @date 2020-02-24.
|
||||
*/
|
||||
|
||||
class SpaceWidget extends StatelessWidget {
|
||||
double height, width;
|
||||
|
||||
SpaceWidget({
|
||||
this.height = 1,
|
||||
this.width = 1,
|
||||
}) : super();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return
|
||||
Container(
|
||||
|
||||
height: height,
|
||||
width: width,
|
||||
color: Colors.transparent,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
flutter/ephemeral/
|
||||
|
||||
# Visual Studio user-specific files.
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Visual Studio build-related files.
|
||||
x64/
|
||||
x86/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
@ -1,102 +0,0 @@
|
||||
# Project-level configuration.
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(timemanagerapp LANGUAGES CXX)
|
||||
|
||||
# The name of the executable created for the application. Change this to change
|
||||
# the on-disk name of your application.
|
||||
set(BINARY_NAME "timemanagerapp")
|
||||
|
||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||
# versions of CMake.
|
||||
cmake_policy(VERSION 3.14...3.25)
|
||||
|
||||
# Define build configuration option.
|
||||
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(IS_MULTICONFIG)
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
|
||||
CACHE STRING "" FORCE)
|
||||
else()
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||
STRING "Flutter build mode" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Profile" "Release")
|
||||
endif()
|
||||
endif()
|
||||
# Define settings for the Profile build mode.
|
||||
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
|
||||
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
|
||||
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
||||
# Use Unicode for all projects.
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
|
||||
# Compilation settings that should be applied to most targets.
|
||||
#
|
||||
# Be cautious about adding new options here, as plugins use this function by
|
||||
# default. In most cases, you should add new options to specific targets instead
|
||||
# of modifying this function.
|
||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_17)
|
||||
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
|
||||
target_compile_options(${TARGET} PRIVATE /EHsc)
|
||||
target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
|
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
|
||||
endfunction()
|
||||
|
||||
# Flutter library and tool build rules.
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||
|
||||
# Application build; see runner/CMakeLists.txt.
|
||||
add_subdirectory("runner")
|
||||
|
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding
|
||||
# them to the application.
|
||||
include(flutter/generated_plugins.cmake)
|
||||
|
||||
|
||||
# === Installation ===
|
||||
# Support files are copied into place next to the executable, so that it can
|
||||
# run in place. This is done instead of making a separate bundle (as on Linux)
|
||||
# so that building and running from within Visual Studio will work.
|
||||
set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
|
||||
# Make the "install" step default, as it's required to run.
|
||||
set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
|
||||
|
||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
if(PLUGIN_BUNDLED_LIBRARIES)
|
||||
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
|
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||
# from a previous install.
|
||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||
" COMPONENT Runtime)
|
||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||
|
||||
# Install the AOT library on non-Debug builds only.
|
||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
CONFIGURATIONS Profile;Release
|
||||
COMPONENT Runtime)
|
||||
@ -1,104 +0,0 @@
|
||||
# This file controls Flutter-level build steps. It should not be edited.
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||
|
||||
# Configuration provided via flutter tool.
|
||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||
|
||||
# TODO: Move the rest of this into files in ephemeral. See
|
||||
# https://github.com/flutter/flutter/issues/57146.
|
||||
set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
|
||||
|
||||
# === Flutter Library ===
|
||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
|
||||
|
||||
# Published to parent scope for install step.
|
||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
|
||||
|
||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||
"flutter_export.h"
|
||||
"flutter_windows.h"
|
||||
"flutter_messenger.h"
|
||||
"flutter_plugin_registrar.h"
|
||||
"flutter_texture_registrar.h"
|
||||
)
|
||||
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
|
||||
add_library(flutter INTERFACE)
|
||||
target_include_directories(flutter INTERFACE
|
||||
"${EPHEMERAL_DIR}"
|
||||
)
|
||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
|
||||
add_dependencies(flutter flutter_assemble)
|
||||
|
||||
# === Wrapper ===
|
||||
list(APPEND CPP_WRAPPER_SOURCES_CORE
|
||||
"core_implementations.cc"
|
||||
"standard_codec.cc"
|
||||
)
|
||||
list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
|
||||
list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
|
||||
"plugin_registrar.cc"
|
||||
)
|
||||
list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
|
||||
list(APPEND CPP_WRAPPER_SOURCES_APP
|
||||
"flutter_engine.cc"
|
||||
"flutter_view_controller.cc"
|
||||
)
|
||||
list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
|
||||
|
||||
# Wrapper sources needed for a plugin.
|
||||
add_library(flutter_wrapper_plugin STATIC
|
||||
${CPP_WRAPPER_SOURCES_CORE}
|
||||
${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||
)
|
||||
apply_standard_settings(flutter_wrapper_plugin)
|
||||
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(flutter_wrapper_plugin PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
|
||||
target_include_directories(flutter_wrapper_plugin PUBLIC
|
||||
"${WRAPPER_ROOT}/include"
|
||||
)
|
||||
add_dependencies(flutter_wrapper_plugin flutter_assemble)
|
||||
|
||||
# Wrapper sources needed for the runner.
|
||||
add_library(flutter_wrapper_app STATIC
|
||||
${CPP_WRAPPER_SOURCES_CORE}
|
||||
${CPP_WRAPPER_SOURCES_APP}
|
||||
)
|
||||
apply_standard_settings(flutter_wrapper_app)
|
||||
target_link_libraries(flutter_wrapper_app PUBLIC flutter)
|
||||
target_include_directories(flutter_wrapper_app PUBLIC
|
||||
"${WRAPPER_ROOT}/include"
|
||||
)
|
||||
add_dependencies(flutter_wrapper_app flutter_assemble)
|
||||
|
||||
# === Flutter tool backend ===
|
||||
# _phony_ is a non-existent file to force this command to run every time,
|
||||
# since currently there's no way to get a full input/output list from the
|
||||
# flutter tool.
|
||||
set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
|
||||
set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
|
||||
add_custom_command(
|
||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||
${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||
${CPP_WRAPPER_SOURCES_APP}
|
||||
${PHONY_OUTPUT}
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
${FLUTTER_TOOL_ENVIRONMENT}
|
||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
|
||||
windows-x64 $<CONFIG>
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(flutter_assemble DEPENDS
|
||||
"${FLUTTER_LIBRARY}"
|
||||
${FLUTTER_LIBRARY_HEADERS}
|
||||
${CPP_WRAPPER_SOURCES_CORE}
|
||||
${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||
${CPP_WRAPPER_SOURCES_APP}
|
||||
)
|
||||
@ -1,14 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <audioplayers_windows/audioplayers_windows_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
AudioplayersWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||
#define GENERATED_PLUGIN_REGISTRANT_
|
||||
|
||||
#include <flutter/plugin_registry.h>
|
||||
|
||||
// Registers Flutter plugins.
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry);
|
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
||||
@ -1,24 +0,0 @@
|
||||
#
|
||||
# Generated file, do not edit.
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
audioplayers_windows
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
|
||||
endforeach(plugin)
|
||||
|
||||
foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
|
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
|
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
|
||||
endforeach(ffi_plugin)
|
||||
@ -1,40 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(runner LANGUAGES CXX)
|
||||
|
||||
# Define the application target. To change its name, change BINARY_NAME in the
|
||||
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
|
||||
# work.
|
||||
#
|
||||
# Any new source files that you add to the application should be added here.
|
||||
add_executable(${BINARY_NAME} WIN32
|
||||
"flutter_window.cpp"
|
||||
"main.cpp"
|
||||
"utils.cpp"
|
||||
"win32_window.cpp"
|
||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||
"Runner.rc"
|
||||
"runner.exe.manifest"
|
||||
)
|
||||
|
||||
# Apply the standard set of build settings. This can be removed for applications
|
||||
# that need different build settings.
|
||||
apply_standard_settings(${BINARY_NAME})
|
||||
|
||||
# Add preprocessor definitions for the build version.
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
|
||||
|
||||
# Disable Windows macros that collide with C++ standard library functions.
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
|
||||
|
||||
# Add dependency libraries and include directories. Add any application-specific
|
||||
# dependencies here.
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
|
||||
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||
|
||||
# Run the Flutter tool portions of the build. This must not be removed.
|
||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||
@ -1,121 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#pragma code_page(65001)
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_APP_ICON ICON "resources\\app_icon.ico"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
|
||||
#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
|
||||
#else
|
||||
#define VERSION_AS_NUMBER 1,0,0,0
|
||||
#endif
|
||||
|
||||
#if defined(FLUTTER_VERSION)
|
||||
#define VERSION_AS_STRING FLUTTER_VERSION
|
||||
#else
|
||||
#define VERSION_AS_STRING "1.0.0"
|
||||
#endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_AS_NUMBER
|
||||
PRODUCTVERSION VERSION_AS_NUMBER
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "com.example" "\0"
|
||||
VALUE "FileDescription", "timemanagerapp" "\0"
|
||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||
VALUE "InternalName", "timemanagerapp" "\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2023 com.example. All rights reserved." "\0"
|
||||
VALUE "OriginalFilename", "timemanagerapp.exe" "\0"
|
||||
VALUE "ProductName", "timemanagerapp" "\0"
|
||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
@ -1,71 +0,0 @@
|
||||
#include "flutter_window.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "flutter/generated_plugin_registrant.h"
|
||||
|
||||
FlutterWindow::FlutterWindow(const flutter::DartProject& project)
|
||||
: project_(project) {}
|
||||
|
||||
FlutterWindow::~FlutterWindow() {}
|
||||
|
||||
bool FlutterWindow::OnCreate() {
|
||||
if (!Win32Window::OnCreate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT frame = GetClientArea();
|
||||
|
||||
// The size here must match the window dimensions to avoid unnecessary surface
|
||||
// creation / destruction in the startup path.
|
||||
flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
|
||||
frame.right - frame.left, frame.bottom - frame.top, project_);
|
||||
// Ensure that basic setup of the controller was successful.
|
||||
if (!flutter_controller_->engine() || !flutter_controller_->view()) {
|
||||
return false;
|
||||
}
|
||||
RegisterPlugins(flutter_controller_->engine());
|
||||
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
||||
|
||||
flutter_controller_->engine()->SetNextFrameCallback([&]() {
|
||||
this->Show();
|
||||
});
|
||||
|
||||
// Flutter can complete the first frame before the "show window" callback is
|
||||
// registered. The following call ensures a frame is pending to ensure the
|
||||
// window is shown. It is a no-op if the first frame hasn't completed yet.
|
||||
flutter_controller_->ForceRedraw();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FlutterWindow::OnDestroy() {
|
||||
if (flutter_controller_) {
|
||||
flutter_controller_ = nullptr;
|
||||
}
|
||||
|
||||
Win32Window::OnDestroy();
|
||||
}
|
||||
|
||||
LRESULT
|
||||
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
|
||||
WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept {
|
||||
// Give Flutter, including plugins, an opportunity to handle window messages.
|
||||
if (flutter_controller_) {
|
||||
std::optional<LRESULT> result =
|
||||
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
|
||||
lparam);
|
||||
if (result) {
|
||||
return *result;
|
||||
}
|
||||
}
|
||||
|
||||
switch (message) {
|
||||
case WM_FONTCHANGE:
|
||||
flutter_controller_->engine()->ReloadSystemFonts();
|
||||
break;
|
||||
}
|
||||
|
||||
return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
#ifndef RUNNER_FLUTTER_WINDOW_H_
|
||||
#define RUNNER_FLUTTER_WINDOW_H_
|
||||
|
||||
#include <flutter/dart_project.h>
|
||||
#include <flutter/flutter_view_controller.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "win32_window.h"
|
||||
|
||||
// A window that does nothing but host a Flutter view.
|
||||
class FlutterWindow : public Win32Window {
|
||||
public:
|
||||
// Creates a new FlutterWindow hosting a Flutter view running |project|.
|
||||
explicit FlutterWindow(const flutter::DartProject& project);
|
||||
virtual ~FlutterWindow();
|
||||
|
||||
protected:
|
||||
// Win32Window:
|
||||
bool OnCreate() override;
|
||||
void OnDestroy() override;
|
||||
LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
|
||||
LPARAM const lparam) noexcept override;
|
||||
|
||||
private:
|
||||
// The project to run.
|
||||
flutter::DartProject project_;
|
||||
|
||||
// The Flutter instance hosted by this window.
|
||||
std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
|
||||
};
|
||||
|
||||
#endif // RUNNER_FLUTTER_WINDOW_H_
|
||||
@ -1,43 +0,0 @@
|
||||
#include <flutter/dart_project.h>
|
||||
#include <flutter/flutter_view_controller.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "flutter_window.h"
|
||||
#include "utils.h"
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
_In_ wchar_t *command_line, _In_ int show_command) {
|
||||
// Attach to console when present (e.g., 'flutter run') or create a
|
||||
// new console when running with a debugger.
|
||||
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
|
||||
CreateAndAttachConsole();
|
||||
}
|
||||
|
||||
// Initialize COM, so that it is available for use in the library and/or
|
||||
// plugins.
|
||||
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
|
||||
flutter::DartProject project(L"data");
|
||||
|
||||
std::vector<std::string> command_line_arguments =
|
||||
GetCommandLineArguments();
|
||||
|
||||
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
|
||||
|
||||
FlutterWindow window(project);
|
||||
Win32Window::Point origin(10, 10);
|
||||
Win32Window::Size size(1280, 720);
|
||||
if (!window.Create(L"timemanagerapp", origin, size)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
window.SetQuitOnClose(true);
|
||||
|
||||
::MSG msg;
|
||||
while (::GetMessage(&msg, nullptr, 0, 0)) {
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
::CoUninitialize();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Runner.rc
|
||||
//
|
||||
#define IDI_APP_ICON 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||