Browse Source

Layout changes:

Input new hover
Checkbox ripple
Row click
master
Eduard Kuzmenko 4 years ago
parent
commit
2a6e7d1178
  1. 9
      src/components/checkboxField.ts
  2. 4
      src/components/ripple.ts
  3. 31
      src/components/row.ts
  4. 3
      src/components/sidebarLeft/tabs/background.ts
  5. 19
      src/components/sidebarLeft/tabs/editProfile.ts
  6. 27
      src/components/sidebarLeft/tabs/generalSettings.ts
  7. 1
      src/components/sidebarLeft/tabs/settings.ts
  8. 10
      src/lib/mtproto/mtprotoworker.ts
  9. 4
      src/scss/components/_global.scss
  10. 5
      src/scss/partials/_checkbox.scss
  11. 27
      src/scss/partials/_input.scss
  12. 27
      src/scss/partials/_leftSidebar.scss
  13. 13
      src/scss/style.scss

9
src/components/checkboxField.ts

@ -1,5 +1,6 @@
import appStateManager from "../lib/appManagers/appStateManager"; import appStateManager from "../lib/appManagers/appStateManager";
import { getDeepProperty } from "../helpers/object"; import { getDeepProperty } from "../helpers/object";
import { ripple } from "./ripple";
export default class CheckboxField { export default class CheckboxField {
public input: HTMLInputElement; public input: HTMLInputElement;
@ -13,7 +14,8 @@ export default class CheckboxField {
stateKey?: string, stateKey?: string,
disabled?: boolean, disabled?: boolean,
checked?: boolean, checked?: boolean,
restriction?: boolean restriction?: boolean,
withRipple?: boolean
} = {}) { } = {}) {
const label = this.label = document.createElement('label'); const label = this.label = document.createElement('label');
label.classList.add('checkbox-field'); label.classList.add('checkbox-field');
@ -86,6 +88,11 @@ export default class CheckboxField {
if(span) { if(span) {
label.append(span); label.append(span);
} }
if(options.withRipple) {
label.classList.add('checkbox-ripple', 'hover-effect');
ripple(label, undefined, undefined, true);
}
} }
get checked() { get checked() {

4
src/components/ripple.ts

@ -3,7 +3,7 @@ import { findUpClassName } from "../helpers/dom";
import rootScope from "../lib/rootScope"; import rootScope from "../lib/rootScope";
let rippleClickId = 0; let rippleClickId = 0;
export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null) { export function ripple(elem: HTMLElement, callback: (id: number) => Promise<boolean | void> = () => Promise.resolve(), onEnd: (id: number) => void = null, prepend = false) {
//return; //return;
if(elem.querySelector('.c-ripple')) return; if(elem.querySelector('.c-ripple')) return;
elem.classList.add('rp'); elem.classList.add('rp');
@ -16,7 +16,7 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
r.classList.add('is-square'); r.classList.add('is-square');
} }
elem.append(r); elem[prepend ? 'prepend' : 'append'](r);
let handler: () => void; let handler: () => void;
//let animationEndPromise: Promise<number>; //let animationEndPromise: Promise<number>;

31
src/components/row.ts

@ -3,6 +3,7 @@ import RadioField from "./radioField";
import { ripple } from "./ripple"; import { ripple } from "./ripple";
import { SliderSuperTab } from "./slider"; import { SliderSuperTab } from "./slider";
import RadioForm from "./radioForm"; import RadioForm from "./radioForm";
import { attachClickEvent, cancelEvent } from "../helpers/dom";
export default class Row { export default class Row {
public container: HTMLElement; public container: HTMLElement;
@ -19,6 +20,7 @@ export default class Row {
subtitle: string, subtitle: string,
radioField: Row['radioField'], radioField: Row['radioField'],
checkboxField: Row['checkboxField'], checkboxField: Row['checkboxField'],
noCheckboxSubtitle: boolean,
title: string, title: string,
titleRight: string, titleRight: string,
clickable: boolean | ((e: Event) => void), clickable: boolean | ((e: Event) => void),
@ -45,8 +47,25 @@ export default class Row {
this.checkboxField = options.checkboxField; this.checkboxField = options.checkboxField;
this.container.append(this.checkboxField.label); this.container.append(this.checkboxField.label);
this.checkboxField.input.addEventListener('change', () => { if(!options.noCheckboxSubtitle) {
this.subtitle.innerHTML = this.checkboxField.input.checked ? 'Enabled' : 'Disabled'; this.checkboxField.input.addEventListener('change', () => {
this.subtitle.innerHTML = this.checkboxField.input.checked ? 'Enabled' : 'Disabled';
});
}
}
const i = options.radioField || options.checkboxField;
i.label.classList.add('disable-hover');
if(options.radioField) {
attachClickEvent(this.container, (e) => {
cancelEvent(e);
i.checked = true;
});
} else {
attachClickEvent(this.container, (e) => {
cancelEvent(e);
i.checked = !i.checked;
}); });
} }
} else { } else {
@ -88,7 +107,7 @@ export default class Row {
options.clickable = () => options.navigationTab.open(); options.clickable = () => options.navigationTab.open();
} }
if(options.clickable) { if(options.clickable || options.radioField || options.checkboxField) {
if(typeof(options.clickable) === 'function') { if(typeof(options.clickable) === 'function') {
this.container.addEventListener('click', (e) => { this.container.addEventListener('click', (e) => {
if(this.freezed) return; if(this.freezed) return;
@ -97,7 +116,11 @@ export default class Row {
} }
this.container.classList.add('row-clickable', 'hover-effect'); this.container.classList.add('row-clickable', 'hover-effect');
ripple(this.container); ripple(this.container, undefined, undefined, true);
/* if(options.radioField || options.checkboxField) {
this.container.prepend(this.container.lastElementChild);
} */
} }
this.container.append(this.subtitle); this.container.append(this.subtitle);

3
src/components/sidebarLeft/tabs/background.ts

@ -31,7 +31,8 @@ export default class AppBackgroundTab extends SliderSuperTab {
const blurCheckboxField = new CheckboxField({ const blurCheckboxField = new CheckboxField({
text: 'Blur Wallpaper Image', text: 'Blur Wallpaper Image',
name: 'blur', name: 'blur',
stateKey: 'settings.background.blur' stateKey: 'settings.background.blur',
withRipple: true
}); });
blurCheckboxField.input.addEventListener('change', () => { blurCheckboxField.input.addEventListener('change', () => {
const active = grid.querySelector('.active') as HTMLElement; const active = grid.querySelector('.active') as HTMLElement;

19
src/components/sidebarLeft/tabs/editProfile.ts

@ -19,7 +19,7 @@ export default class AppEditProfileTab extends SliderSuperTab {
private editPeer: EditPeer; private editPeer: EditPeer;
protected init() { protected async init() {
this.container.classList.add('edit-profile-container'); this.container.classList.add('edit-profile-container');
this.title.innerText = 'Edit Profile'; this.title.innerText = 'Edit Profile';
@ -127,27 +127,16 @@ export default class AppEditProfileTab extends SliderSuperTab {
this.editPeer.nextBtn.removeAttribute('disabled'); this.editPeer.nextBtn.removeAttribute('disabled');
}); });
}, {listenerSetter: this.listenerSetter}); }, {listenerSetter: this.listenerSetter});
}
public fillElements() {
if(this.init) {
this.init();
this.init = null;
}
const user = appUsersManager.getSelf(); const user = appUsersManager.getSelf();
const userFull = await appProfileManager.getProfile(user.id, true);
this.firstNameInputField.setOriginalValue(user.first_name, true); this.firstNameInputField.setOriginalValue(user.first_name, true);
this.lastNameInputField.setOriginalValue(user.last_name, true); this.lastNameInputField.setOriginalValue(user.last_name, true);
this.bioInputField.setOriginalValue('', true); this.bioInputField.setOriginalValue(userFull.about, true);
this.usernameInputField.setOriginalValue(user.username, true); this.usernameInputField.setOriginalValue(user.username, true);
appProfileManager.getProfile(user.id, true).then(userFull => {
if(userFull.about) {
this.bioInputField.setOriginalValue(userFull.about);
}
});
this.setProfileUrl(); this.setProfileUrl();
this.editPeer.handleChange(); this.editPeer.handleChange();
} }

27
src/components/sidebarLeft/tabs/generalSettings.ts

@ -76,7 +76,8 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
const animationsCheckboxField = new CheckboxField({ const animationsCheckboxField = new CheckboxField({
text: 'Enable Animations', text: 'Enable Animations',
name: 'animations', name: 'animations',
stateKey: 'settings.animationsEnabled' stateKey: 'settings.animationsEnabled',
withRipple: true
}); });
container.append(range.container, chatBackgroundButton, animationsCheckboxField.label); container.append(range.container, chatBackgroundButton, animationsCheckboxField.label);
@ -118,22 +119,26 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
const contactsCheckboxField = new CheckboxField({ const contactsCheckboxField = new CheckboxField({
text: 'Contacts', text: 'Contacts',
name: 'contacts', name: 'contacts',
stateKey: 'settings.autoDownload.contacts' stateKey: 'settings.autoDownload.contacts',
withRipple: true
}); });
const privateCheckboxField = new CheckboxField({ const privateCheckboxField = new CheckboxField({
text: 'Private Chats', text: 'Private Chats',
name: 'private', name: 'private',
stateKey: 'settings.autoDownload.private' stateKey: 'settings.autoDownload.private',
withRipple: true
}); });
const groupsCheckboxField = new CheckboxField({ const groupsCheckboxField = new CheckboxField({
text: 'Group Chats', text: 'Group Chats',
name: 'groups', name: 'groups',
stateKey: 'settings.autoDownload.groups' stateKey: 'settings.autoDownload.groups',
withRipple: true
}); });
const channelsCheckboxField = new CheckboxField({ const channelsCheckboxField = new CheckboxField({
text: 'Channels', text: 'Channels',
name: 'channels', name: 'channels',
stateKey: 'settings.autoDownload.channels' stateKey: 'settings.autoDownload.channels',
withRipple: true
}); });
container.append(contactsCheckboxField.label, privateCheckboxField.label, groupsCheckboxField.label, channelsCheckboxField.label); container.append(contactsCheckboxField.label, privateCheckboxField.label, groupsCheckboxField.label, channelsCheckboxField.label);
@ -146,12 +151,14 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
const gifsCheckboxField = new CheckboxField({ const gifsCheckboxField = new CheckboxField({
text: 'GIFs', text: 'GIFs',
name: 'gifs', name: 'gifs',
stateKey: 'settings.autoPlay.gifs' stateKey: 'settings.autoPlay.gifs',
withRipple: true
}); });
const videosCheckboxField = new CheckboxField({ const videosCheckboxField = new CheckboxField({
text: 'Videos', text: 'Videos',
name: 'videos', name: 'videos',
stateKey: 'settings.autoPlay.videos' stateKey: 'settings.autoPlay.videos',
withRipple: true
}); });
container.append(gifsCheckboxField.label, videosCheckboxField.label); container.append(gifsCheckboxField.label, videosCheckboxField.label);
@ -163,12 +170,14 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
const suggestCheckboxField = new CheckboxField({ const suggestCheckboxField = new CheckboxField({
text: 'Suggest Stickers by Emoji', text: 'Suggest Stickers by Emoji',
name: 'suggest', name: 'suggest',
stateKey: 'settings.stickers.suggest' stateKey: 'settings.stickers.suggest',
withRipple: true
}); });
const loopCheckboxField = new CheckboxField({ const loopCheckboxField = new CheckboxField({
text: 'Loop Animated Stickers', text: 'Loop Animated Stickers',
name: 'loop', name: 'loop',
stateKey: 'settings.stickers.loop' stateKey: 'settings.stickers.loop',
withRipple: true
}); });
container.append(suggestCheckboxField.label, loopCheckboxField.label); container.append(suggestCheckboxField.label, loopCheckboxField.label);

1
src/components/sidebarLeft/tabs/settings.ts

@ -112,7 +112,6 @@ export default class AppSettingsTab extends SliderSuperTab {
this.buttons.edit.addEventListener('click', () => { this.buttons.edit.addEventListener('click', () => {
const tab = new AppEditProfileTab(this.slider); const tab = new AppEditProfileTab(this.slider);
tab.fillElements();
tab.open(); tab.open();
}); });

10
src/lib/mtproto/mtprotoworker.ts

@ -55,7 +55,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
private isSWRegistered = true; private isSWRegistered = true;
private debug = DEBUG && false; private debug = DEBUG /* && false */;
private sockets: Map<number, Socket> = new Map(); private sockets: Map<number, Socket> = new Map();
@ -319,7 +319,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
(options as MTMessage).messageId = o.prepareTempMessageId; (options as MTMessage).messageId = o.prepareTempMessageId;
//console.log('will invokeApi:', method, params, options); //console.log('will invokeApi:', method, params, options);
return this.performTaskWorker('invokeApi', method, params, o); return this.invokeApi(method, params, o);
} }
public invokeApiHashable<T extends keyof MethodDeclMap>(method: T, params: Omit<MethodDeclMap[T]['req'], 'hash'> = {} as any, options: InvokeApiOptions = {}): Promise<MethodDeclMap[T]['res']> { public invokeApiHashable<T extends keyof MethodDeclMap>(method: T, params: Omit<MethodDeclMap[T]['req'], 'hash'> = {} as any, options: InvokeApiOptions = {}): Promise<MethodDeclMap[T]['res']> {
@ -334,7 +334,7 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
} }
} }
return this.performTaskWorker('invokeApi', method, params, options).then((result: any) => { return this.invokeApi(method, params, options).then((result: any) => {
if(result._.includes('NotModified')) { if(result._.includes('NotModified')) {
this.debug && this.log.warn('NotModified saved!', method, queryJSON); this.debug && this.log.warn('NotModified saved!', method, queryJSON);
return cached.result; return cached.result;
@ -355,7 +355,9 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
} }
/* private computeHash(smth: any[]) { /* private computeHash(smth: any[]) {
return smth.reduce((hash, v) => (((hash * 0x4F25) & 0x7FFFFFFF) + v.id) & 0x7FFFFFFF, 0); smth = smth.slice().sort((a, b) => a.id - b.id);
//return smth.reduce((hash, v) => (((hash * 0x4F25) & 0x7FFFFFFF) + v.id) & 0x7FFFFFFF, 0);
return smth.reduce((hash, v) => ((hash * 20261) + 0x80000000 + v.id) % 0x80000000, 0);
} */ } */
public setBaseDcId(dcId: number) { public setBaseDcId(dcId: number) {

4
src/scss/components/_global.scss

@ -86,6 +86,10 @@ Utility Classes
display: none !important; display: none !important;
} }
.hide-overflow {
overflow: hidden;
}
// No Text Select // No Text Select
.no-select/* , .no-select * */ { .no-select/* , .no-select * */ {
user-select: none; user-select: none;

5
src/scss/partials/_checkbox.scss

@ -92,6 +92,11 @@
} }
} }
.checkbox-ripple {
overflow: hidden;
border-radius: $border-radius-medium;
}
.checkbox-field-round { .checkbox-field-round {
--size: 1.5rem; --size: 1.5rem;

27
src/scss/partials/_input.scss

@ -70,7 +70,7 @@
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
min-height: var(--height); min-height: var(--height);
transition: .2s border-color; transition: 0s border-color;
position: relative; position: relative;
z-index: 1; z-index: 1;
line-height: 1.3125; line-height: 1.3125;
@ -86,10 +86,16 @@
transition: none; transition: none;
} }
html.no-touch & { @include hover() {
&:hover:not(:focus):not(.error):not(.valid) { &:not(:focus):not(.error):not(.valid) {
border-color: var(--color-gray); //border-color: var(--color-gray);
border-color: #000;
transition: .2s border-color;
} }
/* &:not(:focus):not(.error):not(.valid) ~ label {
transition: .2s transform, .2s padding, .1s opacity, font-weight 0s 1s;
} */
} }
/* font-weight: 500; */ /* font-weight: 500; */
@ -141,6 +147,12 @@
font-weight: 500; font-weight: 500;
} }
// * valid for plain text, empty for contenteditable
&:valid ~ label,
&:not(:empty):focus ~ label {
transition-delay: 0s, 0s, 0s, 0s;
}
&:focus ~ label, &:focus ~ label,
&:valid ~ label, &:valid ~ label,
&:not(:empty) ~ label, &:not(:empty) ~ label,
@ -251,8 +263,11 @@ input:focus, button:focus {
transition: none; transition: none;
} }
&:hover { @include hover() {
border-color: var(--color-gray); &:not(:focus) {
border-color: var(--color-gray) !important;
//border-color: #000;
}
} }
&:focus { &:focus {

27
src/scss/partials/_leftSidebar.scss

@ -501,10 +501,10 @@
.edit-profile-container { .edit-profile-container {
.caption { .caption {
margin-top: 1.063rem; margin-top: 1.0625rem;
margin-left: 1.438rem; margin-left: 1.4375rem;
line-height: 1.2; line-height: var(--line-height);
padding-bottom: 1.438rem; padding-bottom: 1.4375rem;
@include respond-to(handhelds) { @include respond-to(handhelds) {
padding-right: 24px; padding-right: 24px;
@ -512,7 +512,7 @@
} }
.sidebar-left-h2 { .sidebar-left-h2 {
padding: 0 1.438rem; padding: 0 1.4375rem;
padding-bottom: 1.5rem; padding-bottom: 1.5rem;
} }
@ -540,7 +540,7 @@
text-align: center; text-align: center;
color: #707579; color: #707579;
font-size: 14px; font-size: 14px;
line-height: 1.3; line-height: var(--line-height);
} }
} }
@ -836,6 +836,12 @@
> .btn-primary { > .btn-primary {
margin: 0; margin: 0;
} }
> .checkbox-field {
.checkbox-box {
left: auto;
}
}
} }
&-name { &-name {
@ -851,7 +857,7 @@
margin-top: 1rem; margin-top: 1rem;
font-size: 1rem; font-size: 1rem;
color: #707579; color: #707579;
line-height: 1.3125; line-height: var(--line-height);
padding: 0 1rem; padding: 0 1rem;
@include respond-to(handhelds) { @include respond-to(handhelds) {
@ -872,8 +878,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
height: 3.5rem; height: 3.5rem;
margin: 0 1.0625rem; padding: 0 1.1875rem;
padding: 0;
} }
&-disabled { &-disabled {
@ -1032,6 +1037,10 @@
.sidebar-left-section:first-child { .sidebar-left-section:first-child {
padding-bottom: 0; padding-bottom: 0;
.row-title {
font-weight: 500;
}
} }
} }

13
src/scss/style.scss

@ -62,6 +62,7 @@ $chat-padding-handhelds: .5rem;
--messages-container-width: #{$messages-container-width}; --messages-container-width: #{$messages-container-width};
--messages-text-size: 16px; --messages-text-size: 16px;
--messages-secondary-text-size: calc(var(--messages-text-size) - 1px); --messages-secondary-text-size: calc(var(--messages-text-size) - 1px);
--line-height: 1.3125;
--esg-sticker-size: 80px; --esg-sticker-size: 80px;
// https://github.com/overtake/TelegramSwift/blob/5cc7d2475fe4738a6aa0486c23eaf80a89d33b97/submodules/TGUIKit/TGUIKit/PresentationTheme.swift#L2054 // https://github.com/overtake/TelegramSwift/blob/5cc7d2475fe4738a6aa0486c23eaf80a89d33b97/submodules/TGUIKit/TGUIKit/PresentationTheme.swift#L2054
@ -1111,7 +1112,7 @@ middle-ellipsis-element {
} }
&-title { &-title {
line-height: 1.3125; line-height: var(--line-height);
&-right { &-right {
flex: 0 0 auto !important; flex: 0 0 auto !important;
@ -1157,11 +1158,13 @@ middle-ellipsis-element {
&-subtitle { &-subtitle {
color: var(--color-text-secondary) !important; color: var(--color-text-secondary) !important;
font-size: .875rem !important; font-size: .875rem !important;
line-height: var(--line-height);
margin-top: .125rem;
margin-bottom: .0625rem;
// * lol &:empty {
line-height: 1rem; display: none;
margin-top: .1875rem; }
margin-bottom: .125rem;
} }
} }

Loading…
Cancel
Save