Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/icon/is-transparent-crop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icon/is-transparent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions lib/animations/page/slide.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'package:flutter/material.dart';

class SlidePageRoute extends PageRouteBuilder {
final Widget child;
final AxisDirection direction;
final Duration duration;

SlidePageRoute({
super.settings,
required this.child,
this.duration = const Duration(milliseconds: 400),
this.direction = AxisDirection.left,
}) : super(
pageBuilder:
(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) => child,
transitionDuration: duration, // Adjust duration as needed
transitionsBuilder:
(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
Offset beginOffset;
switch (direction) {
case AxisDirection.up:
beginOffset = Offset(0, 1);
break;
case AxisDirection.down:
beginOffset = Offset(0, -1);
break;
case AxisDirection.left:
beginOffset = Offset(1, 0);
break;
case AxisDirection.right:
beginOffset = Offset(-1, 0);
break;
}
final endOffset = Offset(-beginOffset.dx, -beginOffset.dy);

final tween = Tween(begin: beginOffset, end: Offset.zero);
final previousTween = Tween(begin: Offset.zero, end: endOffset);
final curvedAnimation = CurvedAnimation(
parent: animation,
curve: Curves.easeInOut, // Choose your curve
);

return SlideTransition(
position: tween.animate(curvedAnimation),
child: child,
);
},
);
}
7 changes: 4 additions & 3 deletions lib/appstate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import 'dart:convert';
const appStateKey = "app-state";

class AppState {
final models.Session? session;
final models.User? user;
const AppState({this.session, this.user});
models.Session? session;
models.User? user;
AppState({this.session, this.user});
static Future<AppState> load() async {
await Future.delayed(Duration(seconds: 5));
final prefs = await SharedPreferences.getInstance();
final appStateJson = prefs.getString(appStateKey);
if (appStateJson != null) {
Expand Down
33 changes: 23 additions & 10 deletions lib/backend.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,33 @@ Future<Map<String, dynamic>> query(
Map<String, dynamic> data,
models.Session? session,
) async {
final response = await http.post(
Uri.parse("${getBackendBase()}/api/$url"),
body: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
if (session != null) ...{
'session-token': session.token,
'session-id': session.id.toString(),
late http.Response response;
try {
response = await http.post(
Uri.parse("${getBackendBase()}/api/$url"),
body: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
if (session != null) ...{
'session-token': session.token,
'session-id': session.id.toString(),
},
},
},
);
);
} catch (e) {
throw Exception(
'Could not connect to backend, check your internet connection.',
);
}
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to load data from backend(Invalid status code)');
}
}

class Status {
static const notFound = -5;
static const error = -1;
static const ok = 0;
}
1 change: 1 addition & 0 deletions lib/models.dart
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export 'models/session.dart';
export 'models/user.dart';
export 'models/school.dart';
72 changes: 72 additions & 0 deletions lib/models/chatmessage.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import 'dart:ffi';

import 'model.dart';
import 'thread.dart';
import 'user.dart';
import 'session.dart';
import 'package:ins/backend.dart';

class Chatmessage implements Model {
final int id;
final int threadId;
final int userId;
final String content;
final DateTime createdAt;
final DateTime? editedAt;
final Map<int, String> reactions;
final int? repliesTo;
final int? repliesThread;
const Chatmessage({
required this.id,
required this.threadId,
required this.userId,
required this.content,
required this.createdAt,
required this.editedAt,
required this.reactions,
required this.repliesTo,
required this.repliesThread,
});
factory Chatmessage.fromJson(Map<String, dynamic> data) {
return Chatmessage(
id: data['id'] as int,
threadId: data['thread_id'] as int,
userId: data['user_id'] as int,
content: data['content'] as String,
createdAt: DateTime.parse(data['created_at'] as String),
editedAt: data['edited_at'] == null
? null
: DateTime.parse(data['edited_at'] as String),
reactions: data['reactions'] as Map<int, String>,
repliesTo: data['replies_to'] as int?,
repliesThread: data['replies_thread'] as int?,
);
}
@override
Map<String, dynamic> toJson() {
return {
"id": id,
"thread_id": threadId,
"user_id": userId,
"content": content,
"created_at": createdAt.toIso8601String(),
"edited_at": editedAt?.toIso8601String(),
"reactions": reactions,
"replies_to": repliesTo,
"replies_thread": repliesThread,
};
}

Future<Thread> getThread(Session? session) {
return Thread.getByID(session, threadId);
}

Future<User> getUser(Session? session) {
return User.getByID(session, userId);
}

Future<Thread?> getRepliesThread(Session? session) async {
if (repliesThread == null) return null;
return await Thread.getByID(session, repliesThread!);
}
}
62 changes: 62 additions & 0 deletions lib/models/chatroom.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import 'chatserver.dart';

import 'model.dart';
import 'session.dart';
import 'package:ins/backend.dart' as backend;
import 'thread.dart';

class Chatroom implements Model {
final int id;
final String title;
final String? description;
final int? serverId;
final int? threadId;
final DateTime createdAt;
const Chatroom({
required this.id,
required this.title,
required this.description,
required this.serverId,
required this.threadId,
required this.createdAt,
});
factory Chatroom.fromJson(Map<String, dynamic> data) {
return Chatroom(
id: data['id'] as int,
title: data['title'] as String,
description: data['description'] as String?,
serverId: data['server_id'] as int?,
threadId: data['thread_id'] as int?,
createdAt: DateTime.parse(data['created_at'] as String),
);
}
@override
Map<String, dynamic> toJson() {
return {
"id": id,
"title": title,
"description": description,
"server_id": serverId,
"thread_id": threadId,
"created_at": createdAt.toIso8601String(),
};
}

static Future<Chatroom> getById(Session? session, int id) async {
final data = await backend.query("v1/chatroom/get", {"id": id}, session);
if (data['status'] as int < 0) {
throw "Error getting chatroom $id: ${data['message'] as String}";
}
return Chatroom.fromJson(data['room'] as Map<String, dynamic>);
}

Future<Chatserver?> getServer(Session? session) async {
if (serverId == null) return null;
return Chatserver.getById(session, serverId!);
}

Future<Thread?> getThread(Session? session) async {
if (threadId == null) return null;
return Thread.getByID(session, threadId!);
}
}
27 changes: 27 additions & 0 deletions lib/models/chatserver.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'model.dart';
import 'session.dart';
import 'package:ins/backend.dart' as backend;

class Chatserver implements Model {
final int id;
final String fullname;
const Chatserver({required this.id, required this.fullname});
@override
Map<String, dynamic> toJson() {
return {"id": id, "fullname": fullname};
}

factory Chatserver.fromJson(Map<String, dynamic> data) {
return Chatserver(
id: data['id'] as int,
fullname: data['schoolname'] as String,
);
}
static Future<Chatserver> getById(Session? session, int id) async {
final data = await backend.query("v1/chatserver/get", {"id": id}, session);
if (data['status'] as int < 0) {
throw "Error getting charserver $id: ${data['message'] as String}";
}
return Chatserver.fromJson(data['server'] as Map<String, dynamic>);
}
}
68 changes: 68 additions & 0 deletions lib/models/class.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import 'package:ins/models.dart';

import 'school_user.dart';
import 'package:ins/backend.dart' as backend;

import 'model.dart';

class Class implements Model {
final int id;
final int schoolId;
final String fullname;
final int? chatserverId;
final String? description;
final DateTime createdAt;
const Class({
required this.id,
required this.schoolId,
required this.fullname,
required this.chatserverId,
required this.description,
required this.createdAt,
});
@override
Map<String, dynamic> toJson() {
return {
"id": id,
"school_id": schoolId,
"fullname": fullname,
"chatserver_id": chatserverId,
"description": description,
"created_at": createdAt,
};
}

factory Class.fromJson(Map<String, dynamic> data) {
return Class(
id: data['id'] as int,
schoolId: data['school_id'] as int,
fullname: data['schoolname'] as String,
chatserverId: data['schoolserver_id'] as int?,
description: data['description'] as String?,
createdAt: DateTime.parse(data['created_at'] as String),
);
}
static Future<Class> getById(Session? session, int id) async {
final data = await backend.query("v1/class/get", {"id": id}, session);
if (data['status'] as int < 0) {
throw "Error fetching class with id $id: ${data['message'] as String}";
}
return Class.fromJson(data['class']);
}

Future<List<SchoolUser>> getMembers(Session? session) async {
final data = await backend.query("v1/class/getmembers", {
"class_id": id,
}, session);
if (data['status'] as int < 0) {
throw "Error getting members of '$fullname', ${data['message'] as String}";
}
return (data["users"] as List<Map<String, dynamic>>)
.map(SchoolUser.fromJson)
.toList();
}

Future<School> getSchool(Session? session) {
return School.getByID(session, schoolId);
}
}
Loading