REM-Client b4a20f12: QoL - depot search over all depots, depot item by mail, loadout sharing and seller bases (Mark), nav map bookmark folders/colours/export/import/route by double click, group waypoints on the map, price alerts from the dealer, Base Manager page Trade log, friends Invite/Mail (rem-server 69c8c01)

This commit is contained in:
2026-11-10 16:27:30 +01:00
parent 9795731c3c
commit c583a67be4
31 changed files with 90 additions and 11 deletions
+34 -1
View File
@@ -175,6 +175,7 @@
<div class="sep"></div>
<div class="item" data-class-active="page == 10" data-action="page" data-arg="10"><img class="ico" src="3db:INTERFACE/NEURONET/ICONS/NN_Chat.3db"/><span>Mail</span><span class="badge" data-if="mail_unread &gt; 0">{{ mail_unread }}</span><div class="tip">Letters to any pilot, also offline - with credits and items from your depot.</div></div>
<div class="item" data-class-active="page == 11" data-action="page" data-arg="11"><img class="ico" src="3db:INTERFACE/REM/IMAGES/icon_ships.3db"/><span>Loadouts</span><div class="tip">Save your mounted equipment and put it back on with one click - what is missing is bought here.</div></div>
<div class="item" data-class-active="page == 12" data-action="page" data-arg="12"><img class="ico" src="3db:INTERFACE/REM/IMAGES/icon_economy.3db"/><span>Trade log</span><div class="tip">Your buys and sales of commodities with the profit of each sale.</div></div>
</div>
<div class="content" id="base-pages" data-model="base">
<div class="blocked" data-if="blocked != 0">
@@ -204,17 +205,39 @@
<div class="body">
<div class="row" data-for="r : lo_plan" data-class-short="r.short">
<span class="c1">{{ r.b }}</span><span class="c2">{{ r.a }}</span><span class="c3">{{ r.c }}</span><span class="c3">{{ r.d }}</span>
<span class="btn small" data-if="r.e != ''" data-action="lo-mark" data-attr-data-arg="r.key" style="margin-left: 6dp;">Mark<div class="tip">Sets a bookmark on the nav map (folder Loadouts) at the base that sells it.</div></span>
</div>
</div>
</div>
<div class="actions" style="margin-top: 8dp;" data-if="lo_sel">
<div class="btn primary" data-action="lo-apply">Apply<div class="tip">Mounts what is in the hold, buys what is missing on this base and mounts it.</div></div>
<div class="btn" data-action="lo-del">Delete</div>
<div class="btn" data-action="lo-share" data-arg="@group">Share with group<div class="tip">Your group's members get a copy (as "name (from you)").</div></div>
</div>
<div class="actions" style="margin-top: 4dp;" data-if="lo_sel &amp;&amp; lo_friends.size &gt; 0">
<span class="hint" style="margin-right: 6dp;">Send to:</span>
<span class="btn small" data-for="r : lo_friends" data-action="lo-share" data-attr-data-arg="r.key" style="margin: 2dp 4dp 2dp 0;">{{ r.a }}</span>
</div>
<div class="hint" style="margin-top: 8dp;" data-if="lo_msg != ''">{{ lo_msg }}</div>
</div>
</div>
<!-- ================================================= TRADE LOG (REM) -->
<div class="page col" data-if="blocked == 0 &amp;&amp; page == 12">
<div class="col-h"><h3>Trade log</h3><span class="hint">{{ journal.size }} lines</span><div class="btn" data-action="journal-refresh" style="margin-left: 10dp;">Refresh</div></div>
<div class="hint" style="margin-bottom: 6dp;">{{ journal_note }}</div>
<div class="table grow">
<div class="head"><span class="c1" style="width: 130dp; flex: none;">When</span><span class="c2" style="flex: 1;">Deal</span><span class="c2" style="flex: 1;">Base</span><span class="c3" style="width: 150dp; flex: none;">Price (total)</span><span class="c3" style="width: 100dp; flex: none;">Profit</span></div>
<div class="body">
<div class="empty" data-if="journal.size == 0">No trades yet. Buys and sales of commodities show here, a sale with its profit against what you paid.</div>
<div class="row" data-for="r : journal" data-class-short="r.short" data-class-current="r.current">
<span class="c1" style="width: 130dp; flex: none;">{{ r.a }}</span><span class="c2" style="flex: 1;">{{ r.b }}</span><span class="c2" style="flex: 1;">{{ r.c }}</span><span class="c3" style="width: 150dp; flex: none;">{{ r.d }}</span><span class="c3" style="width: 100dp; flex: none;">{{ r.e }}</span>
</div>
</div>
</div>
<div class="hint" style="margin-top: 6dp;">"?" - no profit known: the goods came from elsewhere (a depot, a mission, a trade) or before the log.</div>
</div>
<!-- ================================================= DEPOT -->
<div class="page" data-if="blocked == 0 &amp;&amp; page == 0">
<div class="blocked" data-if="depot_state == 0 &amp;&amp; !depot_remote">
@@ -236,7 +259,7 @@
<div class="head"><span class="c1">Item</span><span class="c2">Type</span><span class="c3">Amount</span></div>
<div class="body">
<div class="empty" data-if="depot.size == 0">{{ depot_state &lt; 0 ? 'Waiting for the server...' : 'The depot is empty.' }}</div>
<div class="row" data-for="r : depot" data-class-selected="r.selected" data-action="pick-depot" data-attr-data-arg="r.key">
<div class="row" data-for="r : depot" data-class-selected="r.selected" data-action="pick-depot" data-ctx="depot" data-attr-data-arg="r.key">
<span class="c1">{{ r.a }}</span><span class="c2">{{ r.b }}</span><span class="c3">{{ r.c }}</span>
</div>
</div>
@@ -266,6 +289,7 @@
<div class="actions">
<div class="btn primary" data-action="withdraw">Withdraw to hold<div class="tip">Moves the amount of the depot item you picked into your cargo hold.</div></div>
<div class="btn primary" data-action="deposit">Deposit to depot<div class="tip">Moves the amount of the cargo you picked into the depot on this base.</div></div>
<div class="btn" data-action="depot-mail">Send by mail<div class="tip">Attaches the amount of the depot item you picked to a new letter (page Mail). A right click on a depot item does it too.</div></div>
</div>
</div>
</div>
@@ -274,6 +298,15 @@
<div class="page col" data-if="blocked == 0 &amp;&amp; page == 1">
<div class="col-h"><h3>Your depots</h3><span class="hint">{{ depots.size }} bases</span></div>
<input class="text search" type="text" data-value="filter" maxlength="40"/>
<div class="hint" data-if="filter == ''">Search a base or an item - every depot that holds it is listed, with how much.</div>
<div class="table" data-if="filter != ''" style="height: 220dp; margin-bottom: 8dp;">
<div class="head"><span class="c1">Item</span><span class="c2">Base</span><span class="c3">Amount</span></div>
<div class="body">
<div class="empty" data-if="depot_find.size == 0">{{ depot_find_note }}</div>
<div class="row" data-for="r : depot_find" data-action="depots-row" data-attr-data-arg="r.key"><span class="c1">{{ r.a }}</span><span class="c2">{{ r.b }}</span><span class="c3">{{ r.c }}</span><div class="tip">Double click: open this depot on the Depot page.</div></div>
</div>
</div>
<div class="hint" data-if="filter != '' &amp;&amp; depot_find.size &gt; 0">{{ depot_find_note }}</div>
<div class="table grow">
<div class="head"><span class="c1">Base</span><span class="c3">Items</span></div>
<div class="body">
+1 -1
View File
@@ -53,7 +53,7 @@
<h3 style="margin: 14dp 0 8dp 0;">Friends</h3>
<div class="hint" data-if="friends.size == 0">No friends yet. Add a pilot by name, or right click a name (chat, contacts) - Add friend.</div>
<div class="member" data-for="f : friends" data-class-on="f.online" style="border-left-color: #6fd08c;">
<span style="flex: 1;">{{ f.name }}</span><span class="w" style="margin-right: 10dp; color: #8197ad;">{{ f.where }}</span><span class="btn small" data-action="friend_remove" data-attr-data-arg="f.name">Remove</span>
<span style="flex: 1;">{{ f.name }}</span><span class="w" style="margin-right: 10dp; color: #8197ad;">{{ f.where }}</span><span class="btn small" data-if="f.online" data-action="friend_invite" data-attr-data-arg="f.name" style="margin-right: 4dp;">Invite<span class="tip">Invites the pilot into your group.</span></span><span class="btn small" data-action="friend_mail" data-attr-data-arg="f.name" style="margin-right: 4dp;">Mail<span class="tip">Writes a letter (base manager, page Mail) - also when the pilot is offline.</span></span><span class="btn small" data-action="friend_remove" data-attr-data-arg="f.name">Remove</span>
</div>
<div style="display: flex; flex-direction: row; align-items: center; margin-top: 8dp;">
<input class="text" type="text" data-value="friend_name" maxlength="32" style="flex: 1; margin-right: 8dp;"/>
+48 -2
View File
@@ -67,6 +67,18 @@
.bookmark .lbl { color: #f2b13c; }
.bookmark.locked .s { border-color: #f2b13c; background-color: #8a6420; }
.bookmark.sel .s { border-color: #ffffff; }
/* REM: a bookmark's own colour over its dot; the group's shared waypoints */
.mi .bc { position: absolute; left: -4dp; top: -4dp; width: 8dp; height: 8dp; border-radius: 4dp; }
.gwp .s { left: -5dp; top: -5dp; width: 10dp; height: 10dp; background-color: #6fd08c; border: 2dp #05080d; transform: rotate(45deg); }
.gwp .lbl { color: #6fd08c; }
.hit.fold { padding: 6dp 10dp 2dp 10dp; color: #f2b13c; font-size: 12dp; border-bottom: 0; }
.hit .dot { width: 8dp; height: 8dp; border-radius: 4dp; margin: 5dp 8dp 0 0; }
.hit .hw { font-size: 11dp; color: #8197ad; margin-left: 6dp; white-space: nowrap; }
.mtools { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; margin: 2dp 10dp 4dp 10dp; }
.mtools .mk { margin: 0 6dp 0 0; padding: 0 6dp; font-size: 11dp; color: #8197ad; border: 1dp #24405c; border-radius: 2dp; }
.mtools .mk:hover, .mtools .mk.on { color: #f2b13c; border-color: #f2b13c; }
.sw { width: 14dp; height: 14dp; border-radius: 7dp; margin: 0 5dp 0 0; border: 1dp #24405c; }
.sw:hover { border-color: #ffffff; }
.hit .mk { margin-left: 6dp; padding: 0 6dp; font-size: 11dp; color: #8197ad; border: 1dp #24405c; border-radius: 2dp; }
.hit .mk:hover { color: #f2b13c; border-color: #f2b13c; }
.hit .mk.del:hover { color: #ef6a5b; border-color: #ef6a5b; }
@@ -119,6 +131,7 @@
<div class="mi" data-for="i : items" data-attr-class="'mi ' + i.cls + (i.selected ? ' sel' : '')" data-style-left="i.left" data-style-top="i.top">
<div class="ring2" data-if="i.selected"></div>
<div class="s" data-style-transform="i.rot"></div>
<div class="bc" data-if="i.color != ''" data-style-background-color="i.color"></div>
<div class="lbl" data-if="i.label != ''" data-style-left="i.lleft" data-style-top="i.ltop">{{ i.label }}</div>
</div>
<div class="pop" data-if="popup" data-style-left="pop_left" data-style-top="pop_top">
@@ -170,9 +183,42 @@
<h3>Known uncharted systems</h3>
<div class="hit" data-for="u : uncharted_list"><span class="hn">{{ u.name }}</span><span class="hk">{{ u.kind }}</span></div>
</div>
<div class="marks" data-if="bookmarks.size &gt; 0 &amp;&amp; search == ''">
<div class="marks" data-if="search == ''">
<h3>Bookmarks</h3>
<div class="hit" data-for="b : bookmarks" data-action="gomark" data-ctx="mark" data-attr-data-arg="b.key"><span class="hn">{{ b.name }}</span><span class="mk" data-action="mark_lock" data-attr-data-arg="b.key">{{ b.kind == 'locked' ? 'Unlock' : 'Lock' }}<span class="tip">{{ b.kind == 'locked' ? 'Locked: it can be neither moved nor deleted. Click to unlock.' : 'Lock it in place: no moving, no deleting.' }}</span></span><span class="mk del" data-if="b.kind != 'locked'" data-action="mark_del" data-attr-data-arg="b.key">&#215;</span></div>
<div class="mtools">
<span class="mk" data-class-on="marks_all" data-action="marks_all">All systems<span class="tip">Every bookmark, of every system - a click goes there, a double click sets a waypoint (the route).</span></span>
<span class="mk" data-action="marks_export">Export<span class="tip">Copies the bookmarks as text (REM-BOOKMARK lines) - to paste into Discord or a file.</span></span>
<span class="mk" data-action="marks_import">Import<span class="tip">Adds the REM-BOOKMARK lines of the clipboard (someone's export).</span></span>
</div>
<div class="hint" style="padding: 2dp 10dp;" data-if="marks_note != ''">{{ marks_note }}</div>
<div class="hint" style="padding: 2dp 10dp;" data-if="bookmarks.size == 0">No bookmarks here. Pick a place and press Bookmark.</div>
<div data-for="b : bookmarks">
<div class="hit fold" data-if="b.kind == 'folder'">{{ b.name }}</div>
<div class="hit" data-if="b.kind != 'folder'" data-action="gomark" data-dbl="markroute" data-ctx="mark" data-attr-data-arg="b.key"><span class="dot" data-style-background-color="b.color"></span><span class="hn">{{ b.name }}</span><span class="hw" data-if="b.where != ''">{{ b.where }}</span><span class="mk" data-action="mark_lock" data-attr-data-arg="b.key">{{ b.kind == 'locked' ? 'Unlock' : 'Lock' }}<span class="tip">{{ b.kind == 'locked' ? 'Locked: it can be neither moved nor deleted. Click to unlock.' : 'Lock it in place: no moving, no deleting.' }}</span></span><span class="mk del" data-if="b.kind != 'locked'" data-action="mark_del" data-attr-data-arg="b.key">&#215;</span><span class="tip">Click: go there. Double click: a waypoint there (the route). Right click: more.</span></div>
</div>
<div data-if="pick_mark" style="margin: 6dp 10dp;">
<div style="display: flex; flex-direction: row; align-items: center;">
<span class="hint" style="margin-right: 6dp;">Folder</span>
<input class="text" type="text" data-value="mark_folder" maxlength="32" style="flex: 1; margin-right: 6dp;"/>
<div class="btn" style="margin: 0; padding: 1dp 8dp;" data-action="mark_folder_set">Set</div>
</div>
<div style="display: flex; flex-direction: row; align-items: center; margin-top: 6dp;">
<span class="hint" style="margin-right: 6dp;">Colour</span>
<span class="sw" style="background-color: #f2b13c;" data-action="mark_color" data-arg=""></span>
<span class="sw" style="background-color: #5cc8f0;" data-action="mark_color" data-arg="#5cc8f0"></span>
<span class="sw" style="background-color: #6fd08c;" data-action="mark_color" data-arg="#6fd08c"></span>
<span class="sw" style="background-color: #ef6a5b;" data-action="mark_color" data-arg="#ef6a5b"></span>
<span class="sw" style="background-color: #b48cf2;" data-action="mark_color" data-arg="#b48cf2"></span>
<span class="sw" style="background-color: #f2e85c;" data-action="mark_color" data-arg="#f2e85c"></span>
<span class="sw" style="background-color: #ffffff;" data-action="mark_color" data-arg="#ffffff"></span>
</div>
</div>
</div>
<div class="marks" data-if="search == ''">
<h3>Group route</h3>
<div class="mtools"><span class="mk" data-class-on="wp_sharing" data-action="wp_share">{{ wp_sharing ? 'Stop sharing' : 'Share my waypoints' }}<span class="tip">Your group sees your waypoints on its map (green diamonds) and can follow them.</span></span></div>
<div class="hint" style="padding: 2dp 10dp;">{{ wp_note }}</div>
<div class="hit" data-for="g : group_wps"><span class="hn">{{ g.name }}</span><span class="hw">{{ g.where }}</span><span class="mk" data-action="wp_follow" data-attr-data-arg="g.name">{{ g.kind == 'following' ? 'Stop following' : 'Follow' }}<span class="tip">Following: that pilot's waypoints become yours (and change with theirs) - the HUD shows them.</span></span></div>
</div>
<div class="pcard" data-if="!has_pick"><div class="k">Click the map to pick a place. Wheel zooms, drag moves, double click opens a system.</div></div>
<div class="objs" data-if="objectives.size &gt; 0">
+4 -4
View File
@@ -67,7 +67,7 @@
<input class="text search" type="text" data-value="filter" maxlength="40"/>
<div class="list">
<div class="empty hint" style="padding: 10dp;" data-if="market.size == 0">Nothing for sale here.</div>
<div class="good" data-for="r : market" data-class-selected="r.selected" data-action="buy-pick" data-dbl="deal" data-attr-data-arg="r.key">
<div class="good" data-for="r : market" data-class-selected="r.selected" data-action="buy-pick" data-dbl="deal" data-ctx="good" data-attr-data-arg="r.key">
<img data-if="r.icon != ''" data-attr-src="r.icon"/><span class="n">{{ r.name }}</span><span class="c">{{ r.count }}</span><span class="p">{{ r.price }}</span>
</div>
</div>
@@ -76,17 +76,17 @@
<div class="col-h"><h3>Your cargo</h3><span class="hint">hold {{ hold }}</span></div>
<div class="list">
<div class="empty hint" style="padding: 10dp;" data-if="cargo.size == 0">Your hold carries no goods.</div>
<div class="good" data-for="r : cargo" data-class-selected="r.selected" data-class-disabled="r.disabled" data-action="sell-pick" data-dbl="deal" data-attr-data-arg="r.key">
<div class="good" data-for="r : cargo" data-class-selected="r.selected" data-class-disabled="r.disabled" data-action="sell-pick" data-dbl="deal" data-ctx="cargo" data-attr-data-arg="r.key">
<img data-if="r.icon != ''" data-attr-src="r.icon"/><span class="n">{{ r.name }}</span><span class="note">{{ r.note }}</span><span class="c">{{ r.count }}</span><span class="p">{{ r.price }}</span>
</div>
</div>
</div>
<div class="colm dest">
<div class="col-h"><h3>{{ has_pick ? 'Sell ' + dest_good + ' at' : 'Where it sells' }}</h3><span class="hint">known bases</span></div>
<div class="col-h"><h3>{{ has_pick ? 'Sell ' + dest_good + ' at' : 'Where it sells' }}</h3><span class="hint">known bases - right click: price alert</span></div>
<div class="list">
<div class="empty hint" style="padding: 10dp;" data-if="!has_pick">Pick a good to see where it sells and for how much.</div>
<div class="empty hint" style="padding: 10dp;" data-if="has_pick &amp;&amp; dests.size == 0">No base you know buys it.</div>
<div class="dst" data-for="d : dests" data-class-best="d.best">
<div class="dst" data-for="d : dests" data-class-best="d.best" data-ctx="dest" data-attr-data-arg="d.key">
<div class="dt"><span class="dn">{{ d.name }}</span><span class="dp">{{ d.price }}</span><span class="df" data-if="d.profit != ''" data-class-loss="d.loss">{{ d.profit }}</span></div>
<div class="ds"><span class="sy">{{ d.system }}</span><span class="bp" data-if="d.baseprice">base price</span><span class="jp" data-class-here="d.here">{{ d.jumps }}</span></div>
</div>