user-complete refactors, challenge complete

complete
Thibault Duplessis 2020-09-11 14:59:10 +02:00
parent f007638922
commit eedbf9e0bc
10 changed files with 55 additions and 34 deletions

View File

@ -69,7 +69,10 @@ object mine {
ctx.isAuth option div(
h2(cls := "ninja-title", "Or invite a Lichess user:"),
br,
postForm(cls := "user-invite", action := routes.Challenge.toFriend(c.id))(
postForm(
cls := "user-invite complete-parent",
action := routes.Challenge.toFriend(c.id)
)(
input(
name := "username",
cls := "friend-autocomplete",

View File

@ -16,6 +16,7 @@ interface Lichess {
jsModule(name: string): string;
loadScript(url: string, opts?: AssetUrlOpts): Promise<void>;
hopscotch: any;
userComplete: () => Promise<UserComplete>;
slider(): Promise<void>;
makeChat(data: any): any;
idleTimer(delay: number, onIdle: () => void, onWakeUp: () => void): void;
@ -35,7 +36,6 @@ interface Lichess {
socket: any;
sound: any;
soundBox: SoundBoxI;
userAutocomplete($input: Cash, opts?: UserAutocompleteOpts): Promise<void>;
miniBoard: {
init(node: HTMLElement): void;
initAll(): void;
@ -81,10 +81,13 @@ interface Lichess {
type RedirectTo = string | { url: string, cookie: Cookie };
interface UserAutocompleteOpts {
type UserComplete = (opts: UserCompleteOpts) => void;
interface UserCompleteOpts {
input: HTMLInputElement,
tag?: 'a' | 'span';
minLength?: number;
select?: (value: string | { id: string; name: string }) => string;
select?: (result: LightUser) => string;
focus?: boolean;
friend?: boolean;
tour?: string;

View File

@ -5,8 +5,8 @@ const li = window.lichess;
export function app($wrap: Cash, toggle: () => void) {
const $input = $wrap.find('input');
li.loadScript(li.jsModule('user-autocomplete')).then(() => {
window.LichessUserAutocomplete({
li.userComplete().then(uac => {
uac({
input: $input[0] as HTMLInputElement,
friend: true,
focus: true

View File

@ -54,7 +54,12 @@ export default function <Result>(opts: Opts<Result>) {
results.forEach(result =>
$(opts.render(result))
.on('click', () => {
opts.input.value = opts.select(result);
/* crazy shit here
just `opts.input.value = opts.select(result);`
does nothing. `opts.select` is not called.
*/
const newValue = opts.select(result);
opts.input.value = newValue;
return true;
})
.appendTo($container)

View File

@ -158,9 +158,9 @@ export default rollupProject({
input: 'src/gameSearch.ts',
output: 'game-search'
},
userAutocomplete: {
input: 'src/user-autocomplete.ts',
output: 'user-autocomplete',
name: 'LichessUserAutocomplete'
userComplete: {
input: 'src/user-complete.ts',
output: 'user-complete',
name: 'UserComplete'
}
});

View File

@ -22,6 +22,7 @@ export default function(opts: ChallengeOpts) {
xhr.text(opts.xhrUrl).then(html => {
$(selector).replaceWith($(html).find(selector));
init();
li.pubsub.emit('content_loaded', $(selector));
});
}
}
@ -41,15 +42,19 @@ export default function(opts: ChallengeOpts) {
$(this).html('<span class="ddloader"></span>');
});
$(selector).find('input.friend-autocomplete').each(function(this: HTMLInputElement) {
const $input = $(this);
li.userAutocomplete($input, {
focus: true,
friend: true,
tag: 'span',
onSelect() {
$input.parents('form').trigger('submit');
}
});
const input = this;
li.userComplete().then(uac =>
uac({
input: input,
friend: true,
tag: 'span',
focus: true,
select: r => {
setTimeout(() => (input.parentNode as HTMLFormElement).submit(), 100);
return r.name;
}
})
)
});
}

View File

@ -9,8 +9,7 @@ export const assetUrl = (path: string, opts: AssetUrlOpts = {}) => {
export const soundUrl = assetUrl('sound', { version: '000003' });
const loadedCss = new Map();
const loadedCss = new Map<string, true>();
export const loadCss = (url: string) => {
if (!loadedCss.has(url)) {
loadedCss.set(url, true);
@ -27,8 +26,16 @@ export const loadCssPath = (key: string) =>
export const jsModule = (name: string) =>
`compiled/${name}${$('body').data('dev') ? '' : '.min'}.js`;
export const loadScript = (url: string, opts: AssetUrlOpts = {}): Promise<void> =>
xhr.script(assetUrl(url, opts));
const loadedScript = new Map<string, Promise<void>>();
export const loadScript = (url: string, opts: AssetUrlOpts = {}): Promise<void> => {
if (!loadedScript.has(url)) loadedScript.set(url, xhr.script(assetUrl(url, opts)));
return loadedScript.get(url)!;
}
export const userComplete = (): Promise<UserComplete> => {
loadCssPath('complete');
return loadScript(jsModule('user-complete')).then(_ => window.UserComplete);
}
export const hopscotch = () => {
loadCss('vendor/hopscotch/dist/css/hopscotch.min.css');

View File

@ -6,7 +6,7 @@ import spinnerHtml from './component/spinner';
import sri from './component/sri';
import { storage, tempStorage } from "./component/storage";
import powertip from "./component/powertip";
import { assetUrl, soundUrl, loadCss, loadCssPath, jsModule, loadScript, hopscotch } from "./component/assets";
import { assetUrl, soundUrl, loadCss, loadCssPath, jsModule, loadScript, hopscotch, userComplete } from "./component/assets";
import widget from "./component/widget";
import idleTimer from "./component/idle-timer";
import pubsub from "./component/pubsub";
@ -38,6 +38,7 @@ export default function() {
l.jsModule = jsModule;
l.loadScript = loadScript;
l.hopscotch = hopscotch;
l.userComplete = userComplete;
l.makeChat = makeChat;
l.idleTimer = idleTimer;
l.pubsub = pubsub;

View File

@ -13,7 +13,7 @@ import timeago from "./component/timeago";
import topBar from "./component/top-bar";
import loadInfiniteScroll from "./component/infinite-scroll";
import { storage } from "./component/storage";
import { assetUrl } from "./component/assets";
import { assetUrl, userComplete } from "./component/assets";
import serviceWorker from "./component/service-worker";
import loadClockWidget from "./component/clock-widget";
import info from "./component/info";
@ -81,14 +81,14 @@ li.load.then(() => {
$('.user-autocomplete').each(function(this: HTMLInputElement) {
const focus = !!this.autofocus;
const start = () => li.loadScript(li.jsModule('user-autocomplete')).then(() => {
window.LichessUserAutocomplete({
const start = () => userComplete().then(uac =>
uac({
input: this,
friend: $(this).data('friend'),
tag: $(this).data('tag'),
focus
});
});
})
);
if (focus) start();
else $(this).one('focus', start);
});

View File

@ -1,4 +1,3 @@
import { loadCssPath } from "./component/assets";
import debounce from 'debounce-promise';
import * as xhr from 'common/xhr';
import complete from 'common/complete';
@ -18,9 +17,7 @@ interface Opts {
swiss?: string;
}
export default function(opts: Opts) {
loadCssPath('complete');
export default function(opts: Opts): void {
complete<Result>({
input: opts.input,