commit b6067074c0aece47207cd426a97abee26e383040 Author: Er2 Date: Sun Nov 7 20:14:25 2021 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..45ba989 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*~ +build/ +# may be in fatpak, maybe not +.flatpak-builder diff --git a/data/gresource.xml b/data/gresource.xml new file mode 100644 index 0000000..237bb92 --- /dev/null +++ b/data/gresource.xml @@ -0,0 +1,19 @@ + + + + style.css + + + diff --git a/data/gschema.xml b/data/gschema.xml new file mode 100644 index 0000000..f18f86e --- /dev/null +++ b/data/gschema.xml @@ -0,0 +1,10 @@ + + + + + 'Er2' + Name + The font to be used for content. + + + diff --git a/data/meson.build b/data/meson.build new file mode 100644 index 0000000..f8ce9a0 --- /dev/null +++ b/data/meson.build @@ -0,0 +1,21 @@ + +gnome = import('gnome') +i18n = import('i18n') + +sch = gnome.compile_schemas(depend_files: 'gschema.xml') +res = gnome.compile_resources( + 'res', 'gresource.xml', + source_dir: 'data', + c_name: 'as' +) +source += res +source += sch + +schemas_dir = datadir /'glib-2.0'/'schemas' + +install_data( + 'gschema.xml', + install_dir: schemas_dir, + rename: [meson.project_name() + '.gschema.xml'] +) +meson.add_install_script('glib-compile-schemas', schemas_dir) diff --git a/data/style.css b/data/style.css new file mode 100644 index 0000000..9e1aa8c --- /dev/null +++ b/data/style.css @@ -0,0 +1,9 @@ +window:not(.maximized) { + border-radius: 8px; +} + +popover arrow { + background: rgba(0,0,0,0); + border: none; +} + diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..3e89df1 --- /dev/null +++ b/meson.build @@ -0,0 +1,52 @@ + +project('org.er2.cord', ['vala', 'c'], version: '1.0') +datadir = get_option('prefix') / get_option('datadir') + +conf = configuration_data() +conf.set_quoted('ID', 'org.er2.cord') # meson.project_name()) +conf.set_quoted('VERSION', meson.project_version()) +conf.set_quoted('GETTEXT_PACKAGE', meson.project_name()) +conf.set_quoted('DATADIR', get_option('prefix') / get_option('datadir')) +conf.set_quoted('GNOMELOCALEDIR', join_paths(get_option('prefix'), get_option('localedir'))) + +configure_file(output: 'config.h', configuration: conf) + +add_project_arguments( + '-include', 'config.h', + language: 'c' +) + +source = files( + 'src/main.vala', + 'src/Launcher.vala', + + 'src/api/Message.vala', + 'src/api/User.vala', + + 'src/screens/Main.vala', + 'src/screens/Settings.vala', + 'src/screens/NewServer.vala', + + 'src/tools/Config.vala', + 'src/tools/CConfig.vapi', + + 'src/widgets/Avatar.vala', + 'src/widgets/Chat.vala', + 'src/widgets/Message.vala', + 'src/widgets/Scroller.vala', +) + +deps = [ + dependency('gtk4') +] + +subdir('data') +subdir('po') + +executable( + 'er2cord', + source, + + dependencies: deps, + install: true +) diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..562ba4c --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1 @@ +ru diff --git a/po/POTFILES b/po/POTFILES new file mode 100644 index 0000000..7a13a07 --- /dev/null +++ b/po/POTFILES @@ -0,0 +1,5 @@ +../src/screens/Main.vala +../src/screens/Settings.vala +../src/screens/NewServer.vala +../src/api/User.vala +../src/widgets/Chat.vala diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 0000000..e9b77d7 --- /dev/null +++ b/po/meson.build @@ -0,0 +1 @@ +i18n.gettext(meson.project_name(), preset: 'glib') diff --git a/po/org.er2.cord.pot b/po/org.er2.cord.pot new file mode 100644 index 0000000..be1c525 --- /dev/null +++ b/po/org.er2.cord.pot @@ -0,0 +1,112 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2021 Er2 +# This file is distributed under Zlib License. +# Er2 , 2021. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: org.er2.cord\n" +"Report-Msgid-Bugs-To: er2+tr@dismail.de\n" +"POT-Creation-Date: 2021-11-07 18:54+0300\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Er2 \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../src/screens/Main.vala:26 +msgid "Er2Cord" +msgstr "" + +#: ../src/screens/Main.vala:42 +msgid "Send" +msgstr "" + +#: ../src/screens/Main.vala:71 +msgid "Me" +msgstr "" + +#: ../src/screens/Main.vala:72 ../src/screens/Settings.vala:12 +msgid "Settings" +msgstr "" + +#: ../src/screens/Main.vala:73 +msgid "Switch account" +msgstr "" + +#: ../src/screens/Main.vala:74 +msgid "Log off" +msgstr "" + +#: ../src/screens/Main.vala:75 +msgid "Quit" +msgstr "" + +#: ../src/screens/Main.vala:79 +msgid "Server" +msgstr "" + +#: ../src/screens/Main.vala:80 +msgid "Account" +msgstr "" + +#: ../src/screens/Main.vala:81 +msgid "Friend" +msgstr "" + +#: ../src/screens/Main.vala:82 +msgid "Invite" +msgstr "" + +#: ../src/screens/Main.vala:84 +msgid "New" +msgstr "" + +#: ../src/screens/NewServer.vala:20 +msgid "Enter" +msgstr "" + +#: ../src/screens/NewServer.vala:45 +msgid "Invite link" +msgstr "" + +#: ../src/screens/NewServer.vala:47 +msgid "Examples:\n" +msgstr "" + +#: ../src/screens/NewServer.vala:57 +msgid "Server name" +msgstr "" + +#: ../src/screens/NewServer.vala:60 +msgid "Server region" +msgstr "" + +#: ../src/screens/NewServer.vala:62 +msgid "By creating a server, you agree to Discord rules" +msgstr "" + +#: ../src/screens/NewServer.vala:64 +msgid "Join" +msgstr "" + +#: ../src/screens/NewServer.vala:65 +msgid "Create" +msgstr "" + +#: ../src/api/User.vala:29 +msgid "Clyde" +msgstr "" + +#: ../src/widgets/Chat.vala:20 +#, c-format +msgid "Welcome to %s!" +msgstr "" + +#: ../src/widgets/Chat.vala:21 +#, c-format +msgid "This is start of the %s." +msgstr "" diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 0000000..1568a7f --- /dev/null +++ b/po/ru.po @@ -0,0 +1,113 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2021 Er2 +# This file is distributed under Zlib License. +# Er2 , 2021. +# +msgid "" +msgstr "" +"Project-Id-Version: org.er2.cord\n" +"Report-Msgid-Bugs-To: er2+tr@dismail.de\n" +"POT-Creation-Date: 2021-11-07 18:54+0300\n" +"PO-Revision-Date: 2021-11-07 19:02+0300\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.0\n" +"Last-Translator: \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" +"Language: ru\n" + +#: ../src/screens/Main.vala:26 +msgid "Er2Cord" +msgstr "Er2Cord" + +#: ../src/screens/Main.vala:42 +msgid "Send" +msgstr "Отправить" + +#: ../src/screens/Main.vala:71 +msgid "Me" +msgstr "Я" + +#: ../src/screens/Main.vala:72 ../src/screens/Settings.vala:12 +msgid "Settings" +msgstr "Настройки" + +#: ../src/screens/Main.vala:73 +msgid "Switch account" +msgstr "Сменить аккаунт" + +#: ../src/screens/Main.vala:74 +msgid "Log off" +msgstr "Выйти из аккаунта" + +#: ../src/screens/Main.vala:75 +msgid "Quit" +msgstr "Выход" + +#: ../src/screens/Main.vala:79 +msgid "Server" +msgstr "Сервер" + +#: ../src/screens/Main.vala:80 +msgid "Account" +msgstr "Аккаунт" + +#: ../src/screens/Main.vala:81 +msgid "Friend" +msgstr "Друг" + +#: ../src/screens/Main.vala:82 +msgid "Invite" +msgstr "Приглашение" + +#: ../src/screens/Main.vala:84 +msgid "New" +msgstr "Новый" + +#: ../src/screens/NewServer.vala:20 +msgid "Enter" +msgstr "Войти" + +#: ../src/screens/NewServer.vala:45 +msgid "Invite link" +msgstr "Ссылка приглашения" + +#: ../src/screens/NewServer.vala:47 +msgid "Examples:\n" +msgstr "Примеры:\n" + +#: ../src/screens/NewServer.vala:57 +msgid "Server name" +msgstr "Имя сервера" + +#: ../src/screens/NewServer.vala:60 +msgid "Server region" +msgstr "Регион сервера" + +#: ../src/screens/NewServer.vala:62 +msgid "By creating a server, you agree to Discord rules" +msgstr "Создавая этот сервер, вы соглашаетесь с правилами Discord" + +#: ../src/screens/NewServer.vala:64 +msgid "Join" +msgstr "Присоединиться" + +#: ../src/screens/NewServer.vala:65 +msgid "Create" +msgstr "Создать" + +#: ../src/api/User.vala:29 +msgid "Clyde" +msgstr "Клайд" + +#: ../src/widgets/Chat.vala:20 +#, c-format +msgid "Welcome to %s!" +msgstr "Добро пожаловать в %s!" + +#: ../src/widgets/Chat.vala:21 +#, c-format +msgid "This is start of the %s." +msgstr "Это начало канала %s." diff --git a/src/Launcher.vala b/src/Launcher.vala new file mode 100644 index 0000000..a8b051e --- /dev/null +++ b/src/Launcher.vala @@ -0,0 +1,48 @@ +/** Launcher of window + * (c) Er2 2021 + * Zlib License + */ + +namespace Er2Cord { + class Launcher : Gtk.Application { + public Config config; + + public Launcher() { + Object( + application_id: ID, + flags: GLib.ApplicationFlags.FLAGS_NONE + ); + actions(); + config = new Config(); + } + public override void activate() { + var win = this.active_window; + if(win == null) win = new AppWindow(this); + win.present(); + } + + public void actions() { + // App-only actions! + add_action_entries({ + {"quit", () => quit() + , null, null, null}, + {"settings", () => { + var wid = new Settings(); + wid.config = this.config; + to_top(wid); + }, null, null, null}, + {"serv", () => to_top(new NewServer()) + , null, null, null}, + }, this); + set_accels_for_action("app.quit", {"q"}); + set_accels_for_action("app.settings", {"s"}); + } + + public void to_top(Gtk.Window wid) { + wid.transient_for = active_window; + wid.modal = true; + wid.application = this; + wid.present(); + } + } +} diff --git a/src/api/Message.vala b/src/api/Message.vala new file mode 100644 index 0000000..b371295 --- /dev/null +++ b/src/api/Message.vala @@ -0,0 +1,56 @@ +/** Message class + * (c) Er2 2021 + * Zlib License + */ + +namespace Er2Cord { + class Message { + public User user; + public string text; + public string date; + public Message? reply; + public MessageEmbed[]? embeds; + public Message( + string text, + User user, + string date = "unk.", + Message? reply = null, + MessageEmbed[]? embeds = null + ) { + this.user = user; + this.text = text; + this.date = date; + this.reply = reply; + this.embeds = embeds; + } + } + + enum EmbedType { + RICH, + IMAGE, + VIDEO, + GIF, + ARTICLE, + LINK, + } + struct EmbedField { + string name; + string value; + bool _inline; + } + struct MessageEmbed { + EmbedType type; + string? title; + string? description; + string? url; + // string? timestamp; + int? color; + //? footer; + //? image; + //? thumbnail; + //? video; + //? provider; + //? author; + EmbedField[]? fields; + } +} diff --git a/src/api/User.vala b/src/api/User.vala new file mode 100644 index 0000000..aab914f --- /dev/null +++ b/src/api/User.vala @@ -0,0 +1,41 @@ +/** User class + * (c) Er2 2021 + * Zlib License + */ + +namespace Er2Cord { + class User { + public Avatar ava; + public string name; + public int discr; + + public static double[] getColors(int k) { + switch(k) { + case 0: return {0.447, 0.537, 0.855}; + case 1: return {0.459, 0.494, 0.541}; + case 2: return {0.231, 0.647, 0.360}; + case 3: return {0.980, 0.651, 0.102}; + case 4: return {0.929, 0.259, 0.271}; + case 5: return {0.922, 0.271, 0.624}; + default: return {0.000, 0.000, 0.000}; + } + } + + public double[] color { + owned get { return getColors(discr % 5); } + } + + public User( + string name = _("Clyde"), + int discr = 0000, + Avatar? ava = null + ) { + this.name = name; + this.discr = discr; + + if(ava == null) + this.ava = new Avatar.gen(name, color); + else this.ava = ava; + } + } +} diff --git a/src/main.vala b/src/main.vala new file mode 100644 index 0000000..90380ea --- /dev/null +++ b/src/main.vala @@ -0,0 +1,9 @@ +/** Startup file + * (c) Er2 2021 + * Zlib License + */ + +static int main (string[] args) { + var app = new Er2Cord.Launcher(); + return app.run(args); +} diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..9b1474d --- /dev/null +++ b/src/meson.build @@ -0,0 +1,36 @@ + +gnome = import('gnome') + +schemas = gnome.compile_schemas() + +source = files( + 'main.vala', + 'Launcher.vala', + + 'api/Message.vala', + 'api/User.vala', + + 'screens/Main.vala', + 'screens/Settings.vala', + 'screens/NewServer.vala', + + 'tools/Config.vala', + + 'widgets/Avatar.vala', + 'widgets/Chat.vala', + 'widgets/Message.vala', + 'widgets/Scroller.vala', +) + +deps = [ + dependency('gtk4') +] + +executable( + 'er2cord', + source, + schemas, + + dependencies: deps, + install: true +) diff --git a/src/screens/Main.vala b/src/screens/Main.vala new file mode 100644 index 0000000..e3d41d5 --- /dev/null +++ b/src/screens/Main.vala @@ -0,0 +1,101 @@ +/** Main window + * (c) Er2 2021 + * Zlib License + */ + +using Gtk; +namespace Er2Cord { + Chat chat; + Scroller gld; + Scroller chn; + Scroller ppl; + + Entry text; + + class AppWindow : ApplicationWindow { + construct { + var css = new CssProvider(); + css.load_from_resource("/org/er2/cord/style.css"); + StyleContext.add_provider_for_display( + get_style_context().display, + css, + STYLE_PROVIDER_PRIORITY_USER + ); + + set_default_size(500, 500); + set_title(_("Er2Cord")); + set_titlebar(win_title()); + + chat = new Chat(new User()); + gld = new Scroller(); + chn = new Scroller(100); + ppl = new Scroller(); + + var main = new Grid(); + main.column_spacing = 2; + + main.attach(chat.scr, 2, 0); + main.attach(chat.user.ava, 0, 1); + main.attach(new Label(chat.user.name), 1, 1); + + text = new Entry(); + var send = new Button.with_label(_("Send")); + text.show_emoji_icon = true; + + text.activate.connect(send_message); + send.clicked.connect(send_message); + + main.attach(text, 2, 1); + main.attach(send, 3, 1); + + main.attach(gld.scr, 0, 0); + main.attach(chn.scr, 1, 0); + main.attach(ppl.scr, 3, 0); + + chat.send_message("hello"); + + child = main; + } + + public Widget win_title() { + var bar = new HeaderBar(); + + var abtn = new MenuButton(); + var mbtn = new MenuButton(); + + var aenu = new GLib.Menu(); + var menu = new GLib.Menu(); + var mfs = new GLib.Menu(); + var mus = new GLib.Menu(); + + mfs.append(_("Me"), "app.me"); + mfs.append(_("Settings"), "app.settings"); + mus.append(_("Switch account"), "app.switch"); + mus.append(_("Log off"), "app.logoff"); + mus.append(_("Quit"), "app.quit"); + menu.append_section(null, mfs); + menu.append_section(null, mus); + + aenu.append(_("Server"), "app.serv"); + aenu.append(_("Account"), "app.login"); + aenu.append(_("Friend"), "app.friend"); + aenu.append(_("Invite"), "app.invite"); + + abtn.label = _("New"); + abtn.menu_model = aenu; + mbtn.menu_model = menu; + + bar.pack_start(abtn); + bar.pack_end(new Separator(VERTICAL)); + bar.pack_end(mbtn); + return bar; + } + + public void send_message() { + chat.send_message(text.text); + text.text = ""; + } + + public AppWindow(Gtk.Application app) { Object(application: app); } + } +} diff --git a/src/screens/NewServer.vala b/src/screens/NewServer.vala new file mode 100644 index 0000000..e3d821f --- /dev/null +++ b/src/screens/NewServer.vala @@ -0,0 +1,68 @@ +/** New server window + * (c) Er2 2021 + * Zlib License + */ + +using Gtk; +namespace Er2Cord { + class NewServer : Window { + Stack stack; + + construct { + stack = new Stack(); + stack.vexpand = stack.hexpand = true; + stack.transition_type = SLIDE_LEFT_RIGHT; + pages(); + + var main = new Box(VERTICAL, 2); + main.append(ava_info()); + main.append(stack); + main.append(new Button.with_label(_("Enter"))); + child = main; + + set_titlebar(win_title()); + } + + public Widget win_title() { + var bar = new HeaderBar(); + var swi = new StackSwitcher(); + swi.stack = stack; + bar.title_widget = swi; + return bar; + } + + public Box ava_info() { + var box = new Box(HORIZONTAL, 2); + box.halign = CENTER; + box.append(new Image.from_icon_name("avatar-default-symbolic")); + box.append(new Label("MyName at Discord")); + return box; + } + + private void pages() { + var jpg = new Box(VERTICAL, 0); + var jlk = new Entry(); + jlk.placeholder_text = _("Invite link"); + jpg.append(jlk); + jpg.append(new Label(_("Examples:\n") + +"""https://discord.gg/discord +discord.gg/discord +discord +""")); + + var cpg = new Grid(); + var csn = new Entry(); + var crg = new ComboBox(); + cpg.row_homogeneous = cpg.column_homogeneous = true; + csn.placeholder_text = _("Server name"); + cpg.attach(csn, 0, 0, 2, 1); + cpg.attach(crg, 1, 1); + cpg.attach(new Label(_("Server region")), 0, 1); + cpg.attach(new Label("TODO: Avatars"), 2, 0, 1, 2); + cpg.attach(new Label(_("By creating a server, you agree to Discord rules")), 0, 2, 2, 1); + + stack.add_titled(jpg, "1", _("Join")); + stack.add_titled(cpg, "2", _("Create")); + } + } +} diff --git a/src/screens/Settings.vala b/src/screens/Settings.vala new file mode 100644 index 0000000..d99b317 --- /dev/null +++ b/src/screens/Settings.vala @@ -0,0 +1,28 @@ +/** Settings window + * (c) Er2 2021 + * Zlib License + */ + +using Gtk; +namespace Er2Cord { + class Settings : Window { + public Config config; + + construct { + set_title(_("Settings")); + set_titlebar(win_title()); + + var main = new Grid(); + main.column_spacing = 2; + + var ent = new Entry(); + + child = main; + } + + public Widget win_title() { + var bar = new HeaderBar(); + return bar; + } + } +} diff --git a/src/tools/CConfig.vapi b/src/tools/CConfig.vapi new file mode 100644 index 0000000..8f2f0a3 --- /dev/null +++ b/src/tools/CConfig.vapi @@ -0,0 +1,8 @@ +[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")] +namespace Er2Cord { + public const string ID; + public const string VERSION; + public const string GETTEXT_PACKAGE; + public const string DATADIR; + public const string GNOMELOCALEDIR; +} diff --git a/src/tools/Config.vala b/src/tools/Config.vala new file mode 100644 index 0000000..d5f90d1 --- /dev/null +++ b/src/tools/Config.vala @@ -0,0 +1,17 @@ +/** Configuration using GSettings + * (c) Er2 2021 + * Zlib License + */ + +namespace Er2Cord { + class Config : GLib.Settings { + public string name { get; set; } + + public Config() { + Object(schema_id: ID); + + // var, class, option flags + bind("name", this, "name", DEFAULT); + } + } +} diff --git a/src/widgets/Avatar.vala b/src/widgets/Avatar.vala new file mode 100644 index 0000000..9561268 --- /dev/null +++ b/src/widgets/Avatar.vala @@ -0,0 +1,73 @@ +/** Avatar widget + * (c) Er2 2021 + * Zlib License + */ + +using Cairo; +namespace Er2Cord { + class Avatar : Gtk.DrawingArea { + public ImageSurface ava; + public int size; + public int round; + + public Avatar(ImageSurface ava, + int size = 32, + int? round = null + ) { + if(round == null) round = size / 2; + content_width = size; + content_height = size; + halign = valign = CENTER; + + this.ava = ava; + this.size = size; + this.round = round; + set_draw_func((th, cr, w, h) => { + cr.set_source_surface(draw(), 0, 0); + cr.paint(); + }); + } + + public Avatar.gen(string name, double[] colors, + int size = 32, + int? round = null + ) { + var sf = new ImageSurface(ARGB32, 256, 256); + var cr = new Context(sf); + cr.set_source_rgb(colors[0], colors[1], colors[2]); + cr.rectangle(0, 0, 256, 256); + cr.paint(); + + cr.set_source_rgb(1, 1, 1); + cr.move_to(75, 170); + cr.set_font_size(128); + cr.show_text(@"$(name[0])"); + + this(sf, size, round); + } + + public ImageSurface draw() { + var x = 0, y = 0, w = size, h = size; + var sf = new ImageSurface(ARGB32, w, h); + var cr = new Context(sf); + + double iw = (double)w / ava.get_width(); + double ih = (double)h / ava.get_height(); + + cr.scale(iw, ih); + cr.set_source_surface(ava, 0, 0); + cr.scale(1.0 / iw, 1.0 / ih); + + cr.new_sub_path(); + cr.arc(x + round, y + round, round, Math.PI, 3 * Math.PI / 2); + cr.arc(x + w - round, y + round, round, 3 * Math.PI / 2, 2 * Math.PI); + cr.arc(x + w - round, y + h - round, round, 0, Math.PI / 2); + cr.arc(x + round, y + h - round, round, Math.PI / 2, Math.PI); + cr.close_path(); + cr.clip(); + cr.paint(); + + return sf; + } + } +} diff --git a/src/widgets/Chat.vala b/src/widgets/Chat.vala new file mode 100644 index 0000000..8ed4352 --- /dev/null +++ b/src/widgets/Chat.vala @@ -0,0 +1,52 @@ +/** Chat class + * (c) Er2 2021 + * Zlib License + */ + +using Gtk; +namespace Er2Cord { + class Chat : Scroller { + public User user; + public string channel; + Message[] msgs; + + public Chat(User user, string channel = "#channelName") { + base(0, new Box(VERTICAL, 0), true); + this.user = user; + this.channel = channel; + //this.msgs = new Message[1]; + + var ava = new Avatar.gen(channel, User.getColors(1), 64); + var big = new Gtk.Label("" + _("Welcome to %s!").printf(channel) + ""); + var txt = new Gtk.Label(_("This is start of the %s.").printf(channel)); + var sep = new Gtk.Separator(HORIZONTAL); + + big.use_markup = true; + big.halign = START; + txt.halign = START; + + sep.margin_start = 8; + sep.margin_end = 8; + sep.margin_top = 8; + sep.margin_bottom = 8; + + append(ava); + append(big); + append(txt); + append(sep); + } + + public bool send_message(string text, Message? reply = null) { + if(text == "") return false; + var msg = new Message(text, user, "\\(*.*)/"); + this.msgs += msg; + append(new MessageWid(msg)); + + // https://stackoverflow.com/a/4479178 + var adj = scr.vadjustment; + adj.value = adj.upper; + scr.vadjustment = adj; + return true; + } + } +} diff --git a/src/widgets/Message.vala b/src/widgets/Message.vala new file mode 100644 index 0000000..6920022 --- /dev/null +++ b/src/widgets/Message.vala @@ -0,0 +1,63 @@ +/** Message widget + * (c) Er2 2021 + * Zlib License + */ + +using Gtk; +namespace Er2Cord { + class MessageWid : Grid { + public Message msg; + + public MessageWid(Message msg) { + this.msg = msg; + column_spacing = 4; + + var rbox = new Box(HORIZONTAL, 4); + if(msg.reply != null) msgReply(rbox); + attach(rbox, 0, 0, 3, 1); + msgHead(); + msgContent(); + } + + public MessageWid.content( + string text, + User user, + string date = "unk.", + Message? reply = null, + MessageEmbed[]? embeds = null + ) { + this(new Message(text, user, date, reply, embeds)); + } + + private void msgReply(Box box) { + var nik = new Label(@"$(msg.reply.user.name)"); + var txt = new Label(string.joinv("\n", msg.reply.text.split("\n", 3)[0:2])); + + nik.use_markup = true; + + box.append(new Image.from_icon_name("mail-replied-symbolic")); + box.append(nik); + box.append(txt); + } + public void msgHead() { + var nick = new Label(@"$(msg.user.name)"); + var date = new Label(msg.date); + nick.use_markup = true; + attach(msg.user.ava, 0, 1); + attach(nick, 1, 1); + attach(date, 2, 1); + } + + public void msgContent() { + var box = new Box(VERTICAL, 0); + var txt = new Label(msg.text); + + txt.halign = START; + txt.wrap = true; + txt.wrap_mode = CHAR; + + box.append(txt); + attach(box, 1, 2, 2, 1); + } + } +} diff --git a/src/widgets/Scroller.vala b/src/widgets/Scroller.vala new file mode 100644 index 0000000..c4989c1 --- /dev/null +++ b/src/widgets/Scroller.vala @@ -0,0 +1,32 @@ +/** Scroller class + * (c) Er2 2021 + * Zlib License + */ + +using Gtk; +namespace Er2Cord { + class Scroller : Object { + Box box; + public ScrolledWindow scr; // FIXME: GTK Developers is pidors + + public Scroller( + int w = 48, + Box wid = new Box(VERTICAL, 0), + bool exp = false + ) { + scr = new ScrolledWindow(); + if(w != 0) scr.width_request = w; + + scr.hscrollbar_policy = NEVER; + scr.vexpand = true; + scr.hexpand = exp; + + box = wid; + scr.child = box; + } + + public void append(Widget w) { + box.append(w); + } + } +}