forked from mystiq/hydrogen-web
add avatar and sender user colors
This commit is contained in:
parent
d33e7b2a8b
commit
44cc691c79
10 changed files with 102 additions and 21 deletions
|
@ -15,6 +15,42 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
export function avatarInitials(name) {
|
||||
const words = name.split(" ").slice(0, 2);
|
||||
return words.reduce((i, w) => i + w.charAt(0).toUpperCase(), "");
|
||||
let words = name.split(" ");
|
||||
if (words.length === 1) {
|
||||
words = words[0].split("-");
|
||||
}
|
||||
words = words.slice(0, 2);
|
||||
return words.reduce((i, w) => {
|
||||
let firstChar = w.charAt(0);
|
||||
if (firstChar === "!" || firstChar === "@" || firstChar === "#") {
|
||||
firstChar = w.charAt(1);
|
||||
}
|
||||
return i + firstChar.toUpperCase();
|
||||
}, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates a numeric hash for a given string
|
||||
*
|
||||
* @param {string} str string to hash
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
function hashCode(str) {
|
||||
let hash = 0;
|
||||
let i;
|
||||
let chr;
|
||||
if (str.length === 0) {
|
||||
return hash;
|
||||
}
|
||||
for (i = 0; i < str.length; i++) {
|
||||
chr = str.charCodeAt(i);
|
||||
hash = ((hash << 5) - hash) + chr;
|
||||
hash |= 0;
|
||||
}
|
||||
return Math.abs(hash);
|
||||
}
|
||||
|
||||
export function getIdentifierColorNumber(id) {
|
||||
return (hashCode(id) % 8) + 1;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {TimelineViewModel} from "./timeline/TimelineViewModel.js";
|
||||
import {avatarInitials} from "../avatar.js";
|
||||
import {avatarInitials, getIdentifierColorNumber} from "../avatar.js";
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
|
||||
export class RoomViewModel extends ViewModel {
|
||||
|
@ -90,7 +90,9 @@ export class RoomViewModel extends ViewModel {
|
|||
return avatarInitials(this._room.name);
|
||||
}
|
||||
|
||||
|
||||
get avatarColorNumber() {
|
||||
return getIdentifierColorNumber(this._room.id)
|
||||
}
|
||||
|
||||
async _sendMessage(message) {
|
||||
if (message) {
|
||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {SimpleTile} from "./SimpleTile.js";
|
||||
import {getIdentifierColorNumber} from "../../../avatar.js";
|
||||
|
||||
export class MessageTile extends SimpleTile {
|
||||
constructor(options) {
|
||||
|
@ -32,6 +33,10 @@ export class MessageTile extends SimpleTile {
|
|||
return this._entry.sender;
|
||||
}
|
||||
|
||||
get senderColorNumber() {
|
||||
return getIdentifierColorNumber(this._entry.sender);
|
||||
}
|
||||
|
||||
get date() {
|
||||
return this._date.toLocaleDateString({}, {month: "numeric", day: "numeric"});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {avatarInitials} from "../avatar.js";
|
||||
import {avatarInitials, getIdentifierColorNumber} from "../avatar.js";
|
||||
import {ViewModel} from "../../ViewModel.js";
|
||||
|
||||
export class RoomTileViewModel extends ViewModel {
|
||||
|
@ -60,4 +60,8 @@ export class RoomTileViewModel extends ViewModel {
|
|||
get avatarInitials() {
|
||||
return avatarInitials(this._room.name);
|
||||
}
|
||||
|
||||
get avatarColorNumber() {
|
||||
return getIdentifierColorNumber(this._room.id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,15 @@ limitations under the License.
|
|||
font-family: 'Inter', sans-serif, 'emoji';
|
||||
background-color: white;
|
||||
color: #2e2f32;
|
||||
|
||||
--usercolor1: #368BD6;
|
||||
--usercolor2: #AC3BA8;
|
||||
--usercolor3: #03B381;
|
||||
--usercolor4: #E64F7A;
|
||||
--usercolor5: #FF812D;
|
||||
--usercolor6: #2DC2C5;
|
||||
--usercolor7: #5C56F5;
|
||||
--usercolor8: #74D12C;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
|
@ -30,6 +39,15 @@ limitations under the License.
|
|||
color: white;
|
||||
}
|
||||
|
||||
.hydrogen .avatar.usercolor1 { background-color: var(--usercolor1); }
|
||||
.hydrogen .avatar.usercolor2 { background-color: var(--usercolor2); }
|
||||
.hydrogen .avatar.usercolor3 { background-color: var(--usercolor3); }
|
||||
.hydrogen .avatar.usercolor4 { background-color: var(--usercolor4); }
|
||||
.hydrogen .avatar.usercolor5 { background-color: var(--usercolor5); }
|
||||
.hydrogen .avatar.usercolor6 { background-color: var(--usercolor6); }
|
||||
.hydrogen .avatar.usercolor7 { background-color: var(--usercolor7); }
|
||||
.hydrogen .avatar.usercolor8 { background-color: var(--usercolor8); }
|
||||
|
||||
.LeftPanel {
|
||||
background: rgba(245, 245, 245, 0.90);
|
||||
}
|
||||
|
@ -135,6 +153,15 @@ a {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hydrogen .sender.usercolor1 { color: var(--usercolor1); }
|
||||
.hydrogen .sender.usercolor2 { color: var(--usercolor2); }
|
||||
.hydrogen .sender.usercolor3 { color: var(--usercolor3); }
|
||||
.hydrogen .sender.usercolor4 { color: var(--usercolor4); }
|
||||
.hydrogen .sender.usercolor5 { color: var(--usercolor5); }
|
||||
.hydrogen .sender.usercolor6 { color: var(--usercolor6); }
|
||||
.hydrogen .sender.usercolor7 { color: var(--usercolor7); }
|
||||
.hydrogen .sender.usercolor8 { color: var(--usercolor8); }
|
||||
|
||||
.TextMessageView .message-container time {
|
||||
padding: 2px 0 0px 20px;
|
||||
font-size: 0.9em;
|
||||
|
|
|
@ -17,9 +17,9 @@ limitations under the License.
|
|||
import {TemplateView} from "../general/TemplateView.js";
|
||||
|
||||
export class RoomTile extends TemplateView {
|
||||
render(t) {
|
||||
render(t, vm) {
|
||||
return t.li({"className": {"active": vm => vm.isOpen}}, [
|
||||
t.div({className: "avatar medium"}, vm => vm.avatarInitials),
|
||||
t.div({className: `avatar medium usercolor${vm.avatarColorNumber}`}, vm => vm.avatarInitials),
|
||||
t.div({className: "description"}, t.div({className: "name"}, vm => vm.name))
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ export class RoomView extends TemplateView {
|
|||
t.div({className: "TimelinePanel"}, [
|
||||
t.div({className: "RoomHeader"}, [
|
||||
t.button({className: "back", onClick: () => vm.close()}),
|
||||
t.div({className: "avatar large"}, vm => vm.avatarInitials),
|
||||
t.div({className: `avatar large usercolor${vm.avatarColorNumber}`}, vm => vm.avatarInitials),
|
||||
t.div({className: "room-description"}, [
|
||||
t.h2(vm => vm.name),
|
||||
]),
|
||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {TemplateView} from "../../../general/TemplateView.js";
|
||||
import {renderMessage} from "./common.js";
|
||||
|
||||
export class ImageView extends TemplateView {
|
||||
render(t, vm) {
|
||||
|
@ -33,13 +34,8 @@ export class ImageView extends TemplateView {
|
|||
style: `padding-top: ${heightRatioPercent}%; width: ${vm.thumbnailWidth}px;`
|
||||
}, image);
|
||||
|
||||
return t.li(
|
||||
{className: {"TextMessageView": true, own: vm.isOwn, pending: vm.isPending}},
|
||||
t.div({className: "message-container"}, [
|
||||
t.div({className: "sender"}, vm => vm.isContinuation ? "" : vm.sender),
|
||||
t.div(linkContainer),
|
||||
t.p(t.time(vm.date + " " + vm.time)),
|
||||
])
|
||||
return renderMessage(t, vm,
|
||||
[t.div(linkContainer), t.p(t.time(vm.date + " " + vm.time))]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,15 +15,12 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {TemplateView} from "../../../general/TemplateView.js";
|
||||
import {renderMessage} from "./common.js";
|
||||
|
||||
export class TextMessageView extends TemplateView {
|
||||
render(t, vm) {
|
||||
return t.li(
|
||||
{className: {"TextMessageView": true, own: vm.isOwn, pending: vm.isPending}},
|
||||
t.div({className: "message-container"}, [
|
||||
t.div({className: "sender"}, vm => vm.isContinuation ? "" : vm.sender),
|
||||
t.p([vm.text, t.time(vm.date + " " + vm.time)]),
|
||||
])
|
||||
return renderMessage(t, vm,
|
||||
[t.p([vm.text, t.time(vm.date + " " + vm.time)])]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
14
src/ui/web/session/room/timeline/common.js
Normal file
14
src/ui/web/session/room/timeline/common.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
export function renderMessage(t, vm, children) {
|
||||
const classes = {
|
||||
"TextMessageView": true,
|
||||
own: vm.isOwn,
|
||||
pending: vm.isPending,
|
||||
continuation: vm.isContinuation,
|
||||
};
|
||||
const sender = t.div({className: `sender usercolor${vm.senderColorNumber}`}, vm => vm.isContinuation ? "" : vm.sender);
|
||||
children = [sender].concat(children);
|
||||
return t.li(
|
||||
{className: classes},
|
||||
t.div({className: "message-container"}, children)
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue