Skip to content

Commit

Permalink
services/notification: helix API
Browse files Browse the repository at this point in the history
- update polling logic
- update access of model data (polling, dispatch, cache item)
- update settings data paths
- refactor dispatch mixin and icon download
- add setBadgeLabel to NwjsService
- rewrite and modernize most tests
  • Loading branch information
bastimeyer committed Jan 16, 2022
1 parent 490633d commit ef8f337
Show file tree
Hide file tree
Showing 16 changed files with 1,198 additions and 1,151 deletions.
24 changes: 10 additions & 14 deletions src/app/services/notification/badge.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
import { get, observer } from "@ember/object";
import { observer } from "@ember/object";
import { and } from "@ember/object/computed";
import { default as Evented, on } from "@ember/object/evented";
import Mixin from "@ember/object/mixin";
import { inject as service } from "@ember/service";
import nwWindow from "nwjs/Window";


export default Mixin.create( Evented, {
/** @type {NwjsService} */
nwjs: service(),
/** @type {SettingsService} */
settings: service(),

// will be overridden by NotificationService
running: false,

_badgeEnabled: and( "running", "settings.notification.badgelabel" ),
_badgeEnabled: and( "running", "settings.content.notification.badgelabel" ),

_badgeEnabledObserver: observer( "_badgeEnabled", function() {
if ( !get( this, "_badgeEnabled" ) ) {
this.badgeSetLabel( "" );
if ( !this._badgeEnabled ) {
this.nwjs.setBadgeLabel( "" );
}
}),

_badgeStreamsAllListener: on( "streams-all", function( streams ) {
if ( streams && get( this, "_badgeEnabled" ) ) {
const length = get( streams, "length" );
this.badgeSetLabel( String( length ) );
if ( streams && this._badgeEnabled ) {
this.nwjs.setBadgeLabel( `${streams.length}` );
}
}),

badgeSetLabel( label ) {
// update badge label or remove it
nwWindow.setBadgeLabel( label );
}
})
});
2 changes: 2 additions & 0 deletions src/app/services/notification/cache/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export function cacheAdd( stream ) {
* @returns {TwitchStream[]}
*/
export function cacheFill( streams, firstRun ) {
streams = streams.slice();

// figure out which streams are new
for ( let item, idx, i = 0, l = cache.length; i < l; i++ ) {
item = cache[ i ];
Expand Down
13 changes: 5 additions & 8 deletions src/app/services/notification/cache/item.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { get } from "@ember/object";


export default class NotificationStreamCacheItem {
/**
* @param {TwitchStream} stream
*/
constructor( stream ) {
this.id = get( stream, "id" );
this.since = get( stream, "created_at" );
this.id = stream.id;
this.since = stream.started_at;
this.fails = 0;
}

Expand All @@ -16,8 +13,8 @@ export default class NotificationStreamCacheItem {
* @returns {Number}
*/
findStreamIndex( streams ) {
for ( let id = this.id, i = 0, l = get( streams, "length" ); i < l; i++ ) {
if ( get( streams[ i ], "id" ) === id ) {
for ( let id = this.id, i = 0, l = streams.length; i < l; i++ ) {
if ( streams[ i ].id === id ) {
return i;
}
}
Expand All @@ -29,6 +26,6 @@ export default class NotificationStreamCacheItem {
* @returns {Boolean}
*/
isNotNewer( stream ) {
return this.since >= get( stream, "created_at" );
return this.since >= stream.started_at;
}
}
44 changes: 21 additions & 23 deletions src/app/services/notification/dispatch.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { get } from "@ember/object";
import { default as Evented, on } from "@ember/object/evented";
import Mixin from "@ember/object/mixin";
import { inject as service } from "@ember/service";
Expand Down Expand Up @@ -33,19 +32,19 @@ export default Mixin.create( Evented, {
*/
async function( streams ) {
if ( !streams ) { return; }
const length = get( streams, "length" );
const { length } = streams;

if ( length > 1 && get( this, "settings.notification.grouping" ) ) {
if ( length > 1 && this.settings.content.notification.grouping ) {
// merge multiple notifications and show a single one
const data = this._getNotificationDataGroup( streams );
await this._showNotification( data );

} else if ( length > 0 ) {
await Promise.all( streams.map( async stream => {
// download channel icon first and save it into a local temp dir...
await iconDownload( stream );
const icon = await iconDownload( stream );
// show notification
const data = this._getNotificationDataSingle( stream );
const data = this._getNotificationDataSingle( stream, icon );
await this._showNotification( data );
}) );
}
Expand All @@ -58,13 +57,13 @@ export default Mixin.create( Evented, {
* @returns {NotificationData}
*/
_getNotificationDataGroup( streams ) {
const settings = get( this, "settings.notification.click_group" );
const settings = this.settings.content.notification.click_group;

return new NotificationData({
title: this.intl.t( "services.notification.dispatch.group" ).toString(),
message: streams.map( stream => ({
title: get( stream, "channel.display_name" ),
message: get( stream, "channel.status" ) || ""
title: stream.user_name,
message: stream.title || ""
}) ),
icon: iconGroup,
click: () => this._notificationClick( streams, settings ),
Expand All @@ -75,16 +74,17 @@ export default Mixin.create( Evented, {
/**
* Show a notification for each stream
* @param {TwitchStream} stream
* @param {string} icon
* @returns {NotificationData}
*/
_getNotificationDataSingle( stream ) {
const settings = get( this, "settings.notification.click" );
const name = get( stream, "channel.display_name" );
_getNotificationDataSingle( stream, icon ) {
const settings = this.settings.content.notification.click;
const name = stream.user_name;

return new NotificationData({
title: this.intl.t( "services.notification.dispatch.single", { name } ).toString(),
message: get( stream, "channel.status" ) || "",
icon: get( stream, "logo" ) || iconGroup,
message: stream.title || "",
icon: icon || iconGroup,
click: () => this._notificationClick( [ stream ], settings ),
settings
});
Expand All @@ -101,13 +101,13 @@ export default Mixin.create( Evented, {
return;
}

logDebug( "Notification click", () => ({
await logDebug( "Notification click", () => ({
action,
streams: streams.mapBy( "id" )
}) );

// restore the window
if ( get( this, "settings.notification.click_restore" ) ) {
if ( this.settings.content.notification.click_restore ) {
setMinimized( false );
setVisibility( true );
setFocused( true );
Expand All @@ -117,21 +117,19 @@ export default Mixin.create( Evented, {
this.router.transitionTo( "user.followedStreams" );

} else if ( action === ATTR_NOTIFY_CLICK_STREAM ) {
const streaming = get( this, "streaming" );
const { streaming } = this;
await Promise.all( streams.map( async stream => {
// don't await startStream promise and ignore errors
streaming.startStream( stream )
.catch( () => {} );
}) );

} else if ( action === ATTR_NOTIFY_CLICK_STREAMANDCHAT ) {
const streaming = get( this, "streaming" );
const openGlobal = get( this, "settings.streams.chat_open" );
const chat = get( this, "chat" );
const { streaming, chat } = this;
const openGlobal = this.settings.content.streams.chat_open;

await Promise.all( streams.map( async stream => {
const channel = get( stream, "channel" );
const { streams_chat_open: openChannel } = await channel.getChannelSettings();
const { streams_chat_open: openChannel } = await stream.getChannelSettings();

// don't await startStream promise and ignore errors
streaming.startStream( stream )
Expand All @@ -150,7 +148,7 @@ export default Mixin.create( Evented, {
return;
}
// don't await openChat promise and ignore errors
chat.openChat( channel )
chat.openChat( stream.user )
.catch( () => {} );
}) );
}
Expand All @@ -161,7 +159,7 @@ export default Mixin.create( Evented, {
* @returns {Promise}
*/
async _showNotification( data ) {
const provider = get( this, "settings.notification.provider" );
const provider = this.settings.content.notification.provider;

// don't await the notification promise here
showNotification( provider, data, false )
Expand Down
22 changes: 13 additions & 9 deletions src/app/services/notification/icons.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { get, set } from "@ember/object";
import { files as filesConfig, notification as notificationConfig } from "config";
import { cachedir } from "utils/node/platform";
import mkdirp from "utils/node/fs/mkdirp";
Expand All @@ -16,6 +15,9 @@ const {
} = notificationConfig;
const iconCacheDir = join( cachedir, cacheName );

/** @type {Map<string, string>} */
const userIconCache = new Map();


// TODO: implement an icon resolver for Linux icon themes
export const iconGroup = resolve( bigIcon );
Expand All @@ -38,17 +40,19 @@ export async function iconDirClear() {

/**
* @param {TwitchStream} stream
* @returns {Promise}
* @returns {Promise<string>}
*/
export async function iconDownload( stream ) {
// don't download logo again if it has already been downloaded
if ( get( stream, "logo" ) ) {
return;
const user = stream.user;
await user.promise;
const { id, profile_image_url } = user.content;

let file = userIconCache.get( id );
if ( !file ) {
file = await download( profile_image_url, iconCacheDir );
userIconCache.set( id, file );
}

const logo = get( stream, "channel.logo" );
const file = await download( logo, iconCacheDir );

// set the local channel logo on the twitchStream record
set( stream, "logo", file );
return file;
}
Loading

0 comments on commit ef8f337

Please sign in to comment.