Skip to content

Commit

Permalink
ユーザー画面でロールのアイコンを表示する
Browse files Browse the repository at this point in the history
  • Loading branch information
poppingmoon committed Jan 4, 2024
1 parent d3aa4de commit b9bd2b5
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 35 deletions.
42 changes: 42 additions & 0 deletions lib/extensions/string_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,46 @@ extension StringExtensions on String {
.replaceAll(Characters(''), Characters('\u{200B}'))
.toString();
}

Color? toColor() {
final code = startsWith("#") ? substring(1) : this;
switch (code.length) {
case 3:
final rgb = code
.split("")
.map((c) => int.tryParse(c, radix: 16))
.nonNulls
.map((i) => i * 16 + i)
.toList();
if (rgb.length == 3) {
return Color.fromRGBO(rgb[0], rgb[1], rgb[2], 1);
}
case 4:
final argb = code
.split("")
.map((c) => int.tryParse(c, radix: 16))
.nonNulls
.map((i) => i * 16 + i)
.toList();
if (argb.length != 4) {
return Color.fromARGB(argb[0], argb[1], argb[2], argb[3]);
}
case 6:
final hex = int.tryParse(code, radix: 16);
if (hex != null) {
return Color(hex + 0xFF000000);
}
case 8:
final hex = int.tryParse(
"${code.substring(6)}${code.substring(0, 6)}",
radix: 16,
);
if (hex != null) {
return Color(hex);
}
default:
return null;
}
return null;
}
}
32 changes: 4 additions & 28 deletions lib/model/color_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:ui';

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:miria/extensions/color_extension.dart';
import 'package:miria/extensions/string_extensions.dart';
import 'package:miria/model/misskey_theme.dart';

part 'color_theme.freezed.dart';
Expand Down Expand Up @@ -80,34 +81,9 @@ class ColorTheme with _$ColorTheme {
return Color.fromRGBO(rgb[0], rgb[1], rgb[2], opacity);
}

final code = (input.startsWith("#") ? input.substring(1) : input);

if (code.length == 3) {
final rgb = code
.split("")
.map((c) => int.parse(c, radix: 16))
.map((i) => i * 16 + i)
.toList();
return Color.fromRGBO(rgb[0], rgb[1], rgb[2], 1);
}
if (code.length == 4) {
final argb = code
.split("")
.map((c) => int.parse(c, radix: 16))
.map((i) => i * 16 + i)
.toList();
return Color.fromARGB(argb[0], argb[1], argb[2], argb[3]);
}
if (code.length == 6) {
return Color(int.parse(code, radix: 16) + 0xFF000000);
}
if (code.length == 8) {
return Color(
int.parse(
"${code.substring(6)}${code.substring(0, 6)}",
radix: 16,
),
);
final color = input.toColor();
if (color != null) {
return color;
}

throw FormatException("invalid color format", val);
Expand Down
50 changes: 43 additions & 7 deletions lib/view/user_page/user_detail.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:confetti/confetti.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:miria/extensions/date_time_extension.dart';
import 'package:miria/extensions/string_extensions.dart';
import 'package:miria/model/account.dart';
import 'package:miria/providers.dart';
import 'package:miria/router/app_router.dart';
Expand All @@ -12,6 +13,7 @@ import 'package:miria/view/common/constants.dart';
import 'package:miria/view/common/error_dialog_handler.dart';
import 'package:miria/view/common/misskey_notes/mfm_text.dart';
import 'package:miria/view/common/misskey_notes/misskey_note.dart';
import 'package:miria/view/common/misskey_notes/network_image.dart';
import 'package:miria/view/dialogs/simple_confirm_dialog.dart';
import 'package:miria/view/themes/app_theme.dart';
import 'package:miria/view/user_page/update_memo_dialog.dart';
Expand Down Expand Up @@ -357,13 +359,7 @@ class UserDetailState extends ConsumerState<UserDetail> {
spacing: 5,
runSpacing: 5,
children: [
for (final role in response.roles ?? [])
Container(
decoration: BoxDecoration(
border:
Border.all(color: Theme.of(context).dividerColor)),
padding: const EdgeInsets.all(5),
child: Text(role.name)),
for (final role in response.roles ?? []) RoleChip(role: role),
],
),
const Padding(padding: EdgeInsets.only(top: 5)),
Expand Down Expand Up @@ -590,6 +586,46 @@ class BirthdayConfettiState extends State<BirthdayConfetti> {
}
}

class RoleChip extends StatelessWidget {
const RoleChip({super.key, required this.role});

final UserRole role;

@override
Widget build(BuildContext context) {
final textStyle = Theme.of(context).textTheme.bodyMedium;
final height = MediaQuery.textScalerOf(context)
.scale((textStyle?.fontSize ?? 14) * (textStyle?.height ?? 1));
return Container(
decoration: BoxDecoration(
border: Border.all(
color: role.color?.toColor() ?? Theme.of(context).dividerColor,
),
borderRadius: BorderRadius.circular(height),
),
padding: const EdgeInsets.symmetric(
vertical: 5,
horizontal: 10,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (role.iconUrl != null)
Padding(
padding: const EdgeInsets.only(right: 5),
child: NetworkImageView(
url: role.iconUrl!.toString(),
type: ImageType.role,
height: height,
),
),
Text(role.name),
],
),
);
}
}

extension on UsersShowResponse {
bool get requiresFollowRequest {
return isLocked &&
Expand Down

0 comments on commit b9bd2b5

Please sign in to comment.