c466a19fc9
NOTE: Only the room owner can delete a room, but they are not able to leave the room. BUG: Deleting or leaving the room deletes the room from disk, but for an unknown reason, the homescreen does not update and still shows the room. Opening and closing the room seems to cause the homescreen to update, removing the room.
319 lines
7.3 KiB
Dart
319 lines
7.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:localstore/localstore.dart';
|
|
|
|
class RoomVisibility {
|
|
final int type;
|
|
const RoomVisibility(this.type);
|
|
|
|
static RoomVisibility get private {
|
|
return const RoomVisibility(0);
|
|
}
|
|
|
|
static RoomVisibility get local {
|
|
return const RoomVisibility(1);
|
|
}
|
|
|
|
static RoomVisibility get public {
|
|
return const RoomVisibility(2);
|
|
}
|
|
|
|
IconData get icon {
|
|
if (type == 2) {
|
|
return Icons.public;
|
|
} else if (type == 1) {
|
|
return Icons.home;
|
|
}
|
|
|
|
return Icons.lock;
|
|
}
|
|
|
|
String get text {
|
|
if (type == 2) {
|
|
return "Global";
|
|
} else if (type == 1) {
|
|
return "Local";
|
|
}
|
|
|
|
return "Private";
|
|
}
|
|
|
|
static List<RoomVisibility> list() {
|
|
return [
|
|
RoomVisibility.private,
|
|
RoomVisibility.local,
|
|
RoomVisibility.public,
|
|
];
|
|
}
|
|
}
|
|
|
|
class RoomIcon {
|
|
final String type;
|
|
RoomIcon({required this.type});
|
|
|
|
static RoomIcon get love {
|
|
return RoomIcon(type: "Love");
|
|
}
|
|
|
|
static RoomIcon get sports {
|
|
return RoomIcon(type: "Sports");
|
|
}
|
|
|
|
static RoomIcon get pets {
|
|
return RoomIcon(type: "Pets");
|
|
}
|
|
|
|
static RoomIcon get vacation {
|
|
return RoomIcon(type: "Vacation");
|
|
}
|
|
|
|
static RoomIcon get gifts {
|
|
return RoomIcon(type: "Gifts");
|
|
}
|
|
|
|
static RoomIcon get groceries {
|
|
return RoomIcon(type: "Groceries");
|
|
}
|
|
|
|
static RoomIcon get fashion {
|
|
return RoomIcon(type: "Fashion");
|
|
}
|
|
|
|
static RoomIcon get art {
|
|
return RoomIcon(type: "Art");
|
|
}
|
|
|
|
static RoomIcon get tech {
|
|
return RoomIcon(type: "Tech");
|
|
}
|
|
|
|
static RoomIcon get home {
|
|
return RoomIcon(type: "Home");
|
|
}
|
|
|
|
static RoomIcon get family {
|
|
return RoomIcon(type: "Family");
|
|
}
|
|
|
|
static RoomIcon get social {
|
|
return RoomIcon(type: "Social");
|
|
}
|
|
|
|
static RoomIcon get other {
|
|
return RoomIcon(type: "Other");
|
|
}
|
|
|
|
static List<RoomIcon> list() {
|
|
return [
|
|
RoomIcon.love,
|
|
RoomIcon.sports,
|
|
RoomIcon.pets,
|
|
RoomIcon.vacation,
|
|
RoomIcon.gifts,
|
|
RoomIcon.groceries,
|
|
RoomIcon.fashion,
|
|
RoomIcon.art,
|
|
RoomIcon.tech,
|
|
RoomIcon.home,
|
|
RoomIcon.family,
|
|
RoomIcon.social,
|
|
RoomIcon.other,
|
|
];
|
|
}
|
|
|
|
String get text {
|
|
switch (type.toLowerCase()) {
|
|
case 'love':
|
|
return 'Friends';
|
|
case 'sports':
|
|
return 'Sports';
|
|
case 'pets':
|
|
return 'Pets';
|
|
case 'vacation':
|
|
return 'Vacation';
|
|
case 'gifts':
|
|
return 'Gifts';
|
|
case 'groceries':
|
|
return 'Groceries';
|
|
case 'fashion':
|
|
return 'Clothing';
|
|
case 'art':
|
|
return 'Arts & Crafts';
|
|
case 'tech':
|
|
return 'Electronics';
|
|
case 'home':
|
|
return 'Home supplies';
|
|
case 'family':
|
|
return 'Family';
|
|
case 'social':
|
|
return 'Social';
|
|
case 'other':
|
|
default:
|
|
return 'Other';
|
|
}
|
|
}
|
|
|
|
// return image name
|
|
String get img {
|
|
switch (type.toLowerCase()) {
|
|
case 'love':
|
|
return 'undraw/undraw_couple.svg';
|
|
case 'sports':
|
|
return 'undraw/undraw_greek_freak.svg';
|
|
case 'pets':
|
|
return 'undraw/undraw_dog.svg';
|
|
case 'vacation':
|
|
return 'undraw/undraw_trip.svg';
|
|
case 'gifts':
|
|
return 'undraw/undraw_gifts.svg';
|
|
case 'groceries':
|
|
return 'undraw/undraw_gone_shopping.svg';
|
|
case 'fashion':
|
|
return 'undraw/undraw_jewelry.svg';
|
|
case 'art':
|
|
return 'undraw/undraw_sculpting.svg';
|
|
case 'tech':
|
|
return 'undraw/undraw_progressive_app.svg';
|
|
case 'home':
|
|
return 'undraw/undraw_under_construction.svg';
|
|
case 'family':
|
|
return 'undraw/undraw_family.svg';
|
|
case 'social':
|
|
return 'undraw/undraw_pizza_sharing.svg';
|
|
case 'other':
|
|
default:
|
|
return 'undraw/undraw_file_manager.svg';
|
|
}
|
|
}
|
|
}
|
|
|
|
class Room {
|
|
final String id;
|
|
final String serverTag;
|
|
final String name;
|
|
final String description;
|
|
RoomIcon? icon = RoomIcon.other;
|
|
RoomVisibility? visibility = RoomVisibility.private;
|
|
|
|
Room(
|
|
{required this.id,
|
|
required this.serverTag,
|
|
this.name = "",
|
|
this.description = "",
|
|
this.icon,
|
|
this.visibility});
|
|
|
|
// get list of all known rooms
|
|
static Future<List<Room>> listRooms() async {
|
|
final db = Localstore.instance;
|
|
final rooms = (await db.collection('rooms').get())!;
|
|
List<Room> builder = [];
|
|
for (MapEntry entry in rooms.entries) {
|
|
try {
|
|
builder.add(Room.fromMap(entry.value));
|
|
} catch (e) {
|
|
// skip invalid rooms
|
|
// NOTE: might want to autodelete them in the future
|
|
// although keeping them might be ok,
|
|
// in case we ever get a new dataset to fix the current state
|
|
}
|
|
}
|
|
return builder;
|
|
}
|
|
|
|
// listen to room change
|
|
static listen(Function(Map<String, dynamic>) cb) async {
|
|
final db = Localstore.instance;
|
|
final stream = db.collection('rooms').stream;
|
|
stream.listen(cb);
|
|
}
|
|
|
|
factory Room.fromMap(Map<String, dynamic> map) {
|
|
return Room(
|
|
id: map['id'],
|
|
serverTag: map['server'],
|
|
name: map['name'],
|
|
description: map['description'] ?? '',
|
|
icon: RoomIcon(type: map['icon'] ?? 'Other'),
|
|
visibility: RoomVisibility(map['visibility'] ?? 0));
|
|
}
|
|
|
|
Map<String, dynamic> toMap() {
|
|
return {
|
|
'id': id,
|
|
'server': serverTag,
|
|
'description': description,
|
|
'name': name,
|
|
'icon': icon?.type,
|
|
'visibility': visibility?.type
|
|
};
|
|
}
|
|
|
|
factory Room.fromJSON(dynamic json) {
|
|
return Room(
|
|
id: json['name'],
|
|
serverTag: json['server'],
|
|
name: json['title'],
|
|
description: json['description'],
|
|
icon: RoomIcon(type: json['icon']),
|
|
visibility: RoomVisibility(json['visibility']));
|
|
}
|
|
|
|
Future<void> toDisk() async {
|
|
final db = Localstore.instance;
|
|
await db.collection('rooms').doc('$id@$serverTag').set(toMap());
|
|
}
|
|
|
|
Future<void> removeDisk() async {
|
|
final db = Localstore.instance;
|
|
// NOTE: Because categories, products and entries
|
|
// are supposed to be stored in the room object
|
|
// (they are just not read by Room.fromDisk)
|
|
// deleting the document from the collection
|
|
// should also get rid of affiliated collections
|
|
await db.collection('rooms').doc('$id@$serverTag').delete();
|
|
}
|
|
|
|
static Future<Room> fromDisk(
|
|
{required String id, required String serverTag}) async {
|
|
final db = Localstore.instance;
|
|
final raw = await db.collection('rooms').doc('$id@$serverTag').get();
|
|
return Room.fromMap(raw!);
|
|
}
|
|
}
|
|
|
|
class ShoppingListItem {}
|
|
|
|
class RoomMember {
|
|
final String id;
|
|
final String serverTag;
|
|
final bool isAdmin;
|
|
|
|
const RoomMember(
|
|
{required this.id, required this.serverTag, required this.isAdmin});
|
|
|
|
factory RoomMember.fromJSON(dynamic json) {
|
|
return RoomMember(
|
|
id: json['name'], serverTag: json['server'], isAdmin: json['admin']);
|
|
}
|
|
}
|
|
|
|
class RoomInfo {
|
|
final String owner;
|
|
final bool isAdmin;
|
|
final bool isOwner;
|
|
final int permissions;
|
|
|
|
const RoomInfo(
|
|
{required this.permissions,
|
|
required this.owner,
|
|
required this.isAdmin,
|
|
required this.isOwner});
|
|
|
|
factory RoomInfo.fromJSON(dynamic json) {
|
|
return RoomInfo(
|
|
permissions: json['rights'],
|
|
owner: json['owner'],
|
|
isAdmin: json['isAdmin'],
|
|
isOwner: json['isOwner']);
|
|
}
|
|
}
|