Compare commits

...

3 Commits

Author SHA1 Message Date
Diogo e97eb77960 fix lib build 2024-12-09 10:41:04 +00:00
Evgeny Poberezkin 2bef6139ae notice 2024-12-06 22:49:46 +00:00
Evgeny Poberezkin bb0ac16642 rfc: chat tags 2024-12-06 22:42:42 +00:00
5 changed files with 116 additions and 0 deletions
@@ -512,6 +512,7 @@ struct ChatListSearchBar: View {
var body: some View {
VStack(spacing: 12) {
ScrollView([.horizontal], showsIndicators: false) { ChatTagsView() }
HStack(spacing: 12) {
HStack(spacing: 4) {
Image(systemName: "magnifyingglass")
@@ -605,6 +606,58 @@ struct ChatListSearchBar: View {
}
}
enum ChatTag: Identifiable, Equatable {
case presetTag(icon: String, activeIcon: String)
case chatTag(emoji: String, text: String)
var id: String {
switch self {
case let .presetTag(icon, _): "preset \(icon)"
case let .chatTag(emoji, _): "chatTag \(emoji)"
}
}
}
struct ChatTagsView: View {
var chatTags: [ChatTag] = [
.presetTag(icon: "star", activeIcon: "star.fill"),
.presetTag(icon: "person", activeIcon: "person.fill"),
.presetTag(icon: "person.2", activeIcon: "person.2.fill"),
.presetTag(icon: "briefcase", activeIcon: "briefcase.fill"),
.chatTag(emoji: "🧑‍💻", text: "Work"),
.chatTag(emoji: "🤝", text: "Friends"),
.chatTag(emoji: "🐸", text: "Memes")
]
@State var selectedTag: ChatTag?
var body: some View {
HStack {
ForEach(chatTags) { tag in
let current = selectedTag == tag
let color: Color = current ? .accentColor : .secondary
ZStack {
switch tag {
case let .presetTag(icon, activeIcon):
Image(systemName: current ? activeIcon : icon)
.foregroundColor(color)
case let .chatTag(emoji, text):
HStack(spacing: 4) {
Text(emoji)
ZStack {
Text(text).fontWeight(.medium).foregroundColor(.clear)
Text(text).fontWeight(current ? .medium : .regular).foregroundColor(color)
}
}
}
}
.onTapGesture {
selectedTag = tag
}
}
}
}
}
func chatStoppedIcon() -> some View {
Button {
AlertManager.shared.showAlertMsg(
Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

+25
View File
@@ -0,0 +1,25 @@
# Chat tags, emoji entry
## Problem
Organize chats.
Stop users from using chat profiles to organize chats.
More fun as we solve groups problem.
## Solution
This is a simple "quality of life" improvement that's long due, as the number of users and conversations grows, that would probably take just a week to ship.
Proposed UX:
- tags are per profile.
- preset tags for favourites, contacts, groups and business chats.
- user defined tags *must* have text and emoji.
- if some conversation tag (preset or user defined) is not present in the conversation, the tag will not show in the bar, but would still allow selecting it when tagging.
- there should be some way to delete tag completely, maybe on long-press on tab bar or maybe in the list of tags?
- tagging conversation will be done via the context menu that will open a second menu allowing to choose from existing tag or add a new type and select emoji (which means we need to add our embedded emoji keyboard on desktop and on android, and that should be used in compose too, as many desktop platforms and older android do not allow choosing emoji easily). We could also switch android to emoji font we use on desktop, if it's not too large, as default Android emoji are quite ugly.
- on iOS it would be a third "..." button on the trailing swipe area, which will consume Delete button for groups. If there is only Tag button, we don't need "...", we should use Tag directly.
- it also needs some removable notice, once there are conversations, so there will be some preset tag(s), but no user-defined tags (tappable "Tag your chats" with info on how to tag with X to remove and maybe alert if info was not opened).
![UI](2024-12-06-chat-tags.jpg)
+1
View File
@@ -155,6 +155,7 @@ library
Simplex.Chat.Migrations.M20241125_indexes
Simplex.Chat.Migrations.M20241128_business_chats
Simplex.Chat.Migrations.M20241205_business_chat_members
Simplex.Chat.Migrations.M20241206_chat_tags
Simplex.Chat.Mobile
Simplex.Chat.Mobile.File
Simplex.Chat.Mobile.Shared
@@ -0,0 +1,37 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Migrations.M20241206_chat_tags where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20241205_business_chat_members :: Query
m20241205_business_chat_members =
[sql|
CREATE TABLE chat_tags (
chat_tag_id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER REFERENCES users;
chat_tag_text TEXT NOT NULL UNIQUE,
chat_tag_emoji TEXT NOT NULL UNIQUE
);
ALTER TABLE contacts ADD COLUMN chat_tag_id REFERENCES chat_tags;
ALTER TABLE groups ADD COLUMN chat_tag_id REFERENCES chat_tags;
CREATE INDEX idx_chat_tags_user_id ON chat_tags(user_id);
CREATE INDEX idx_contacts_chat_tag_id ON contacts(chat_tag_id);
CREATE INDEX idx_groups_chat_tag_id ON groups(chat_tag_id);
|]
down_m20241205_business_chat_members :: Query
down_m20241205_business_chat_members =
[sql|
DROP INDEX idx_contacts_chat_tag_id;
DROP INDEX idx_groups_chat_tag_id;
ALTER TABLE contacts DROP COLUMN;
ALTER TABLE groups DROP COLUMN;
DROP TABLE chat_tags
|]