Initial commit: JustAMessenger v0.1.0
Серверная часть (Go): - WebSocket сервер с бинарным протоколом - XChaCha20-Poly1305 шифрование - zstd сжатие с дедупликацией (64KB чанки) - SQLite хранилище (WAL режим) - Управление гильдиями, каналами, ролями - Федерация между серверами (ed25519) - REST API + WebSocket endpoints Клиентская часть (Flutter): - Material Design 3 тёмная тема (Discord-like) - WebSocket соединение с сервером - Экраны: сплэш, логин, домашний, гильдии, чат - Модели: пользователи, гильдии, каналы, сообщения, роли - Сервисы: соединение, API, криптография, тема - Виджеты: иконки гильдий, сообщения, ввод чата - Web сборка (PWA) Документация: - AGENTS.md — контекст для ИИ ассистентов - docs/protocol.md — спецификация протокола
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../services/theme_service.dart';
|
||||
|
||||
class GuildIcon extends StatelessWidget {
|
||||
final String name;
|
||||
final String? icon;
|
||||
final bool selected;
|
||||
final double size;
|
||||
|
||||
const GuildIcon({
|
||||
super.key,
|
||||
required this.name,
|
||||
this.icon,
|
||||
this.selected = false,
|
||||
this.size = 48,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final borderRadius = selected ? 14.0 : 24.0;
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
if (selected)
|
||||
Positioned(
|
||||
left: -8,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Container(
|
||||
width: 4,
|
||||
height: size * 0.4,
|
||||
decoration: BoxDecoration(
|
||||
color: ThemeService.textPrimary,
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: size * 0.25),
|
||||
child: Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
color: selected
|
||||
? ThemeService.primary
|
||||
: ThemeService.surfacePrimary,
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
),
|
||||
child: Center(
|
||||
child: icon != null
|
||||
? ClipRRect(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
child: Image.network(
|
||||
icon!,
|
||||
width: size,
|
||||
height: size,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, __, ___) => _buildInitial(),
|
||||
),
|
||||
)
|
||||
: _buildInitial(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInitial() {
|
||||
return Text(
|
||||
name.isNotEmpty ? name[0].toUpperCase() : '?',
|
||||
style: TextStyle(
|
||||
color: selected ? Colors.white : ThemeService.textSecondary,
|
||||
fontSize: size * 0.4,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user