1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-05-06 05:34:05 +02:00

Update and add analytics data points & increase report interval to 14 days

This commit is contained in:
chylex 2018-02-11 20:01:57 +01:00
parent cb9f75e968
commit 50e39164bd
12 changed files with 82 additions and 20 deletions

View File

@ -16,7 +16,7 @@
using TweetDuck.Updates;
namespace TweetDuck.Core{
sealed partial class FormBrowser : Form{
sealed partial class FormBrowser : Form, AnalyticsFile.IProvider{
private static UserConfig Config => Program.UserConfig;
public bool IsWaiting{
@ -219,7 +219,7 @@ private void plugins_Reloaded(object sender, PluginErrorEventArgs e){
}
if (isLoaded){
ReloadToTweetDeck();
browser.ReloadToTweetDeck();
}
}
@ -295,6 +295,7 @@ public void ReinjectCustomCSS(string css){
public void ReloadToTweetDeck(){
browser.ReloadToTweetDeck();
AnalyticsFile.CountBrowserReloads.Trigger();
}
public void TriggerTweetScreenshot(){
@ -311,6 +312,7 @@ public void PlaySoundNotification(){
public void ApplyROT13(){
browser.ApplyROT13();
AnalyticsFile.CountUsedROT13.Trigger();
}
// callback handlers

View File

@ -11,6 +11,7 @@
using TweetDuck.Core.Management;
using TweetDuck.Core.Notification;
using TweetDuck.Core.Other;
using TweetDuck.Core.Other.Analytics;
namespace TweetDuck.Core.Handling{
abstract class ContextMenuBase : IContextMenuHandler{
@ -44,6 +45,12 @@ private static string GetMediaLink(IContextMenuParams parameters){
private string[] lastHighlightedTweetAuthors;
private string[] lastHighlightedTweetImageList;
private readonly AnalyticsFile.IProvider analytics;
protected ContextMenuBase(AnalyticsFile.IProvider analytics){
this.analytics = analytics;
}
public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
if (!TwitterUtils.IsTweetDeckWebsite(frame) || browser.IsLoading){
lastHighlightedTweetAuthors = StringUtils.EmptyArray;
@ -97,26 +104,29 @@ public virtual void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser bro
}
public virtual bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags){
Control control = browserControl.AsControl();
switch(commandId){
case MenuOpenLinkUrl:
OpenBrowser(browserControl.AsControl(), IsLink ? ContextInfo.Value : parameters.LinkUrl);
OpenBrowser(control, IsLink ? ContextInfo.Value : parameters.LinkUrl);
break;
case MenuCopyLinkUrl:
SetClipboardText(browserControl.AsControl(), IsLink ? ContextInfo.Value : parameters.UnfilteredLinkUrl);
SetClipboardText(control, IsLink ? ContextInfo.Value : parameters.UnfilteredLinkUrl);
break;
case MenuCopyUsername:
Match match = TwitterUtils.RegexAccount.Match(parameters.UnfilteredLinkUrl);
SetClipboardText(browserControl.AsControl(), match.Success ? match.Groups[1].Value : parameters.UnfilteredLinkUrl);
SetClipboardText(control, match.Success ? match.Groups[1].Value : parameters.UnfilteredLinkUrl);
control.InvokeAsyncSafe(analytics.AnalyticsFile.CountCopiedUsernames.Trigger);
break;
case MenuOpenMediaUrl:
OpenBrowser(browserControl.AsControl(), TwitterUtils.GetMediaLink(GetMediaLink(parameters), ImageQuality));
OpenBrowser(control, TwitterUtils.GetMediaLink(GetMediaLink(parameters), ImageQuality));
break;
case MenuCopyMediaUrl:
SetClipboardText(browserControl.AsControl(), TwitterUtils.GetMediaLink(GetMediaLink(parameters), ImageQuality));
SetClipboardText(control, TwitterUtils.GetMediaLink(GetMediaLink(parameters), ImageQuality));
break;
case MenuViewImage:
@ -138,6 +148,8 @@ void ViewFile(){
ViewFile();
}
else{
control.InvokeAsyncSafe(analytics.AnalyticsFile.CountViewedImages.Trigger);
BrowserUtils.DownloadFileAsync(TwitterUtils.GetMediaLink(url, ImageQuality), file, ViewFile, ex => {
FormMessage.Error("Image Download", "An error occurred while downloading the image: "+ex.Message, FormMessage.OK);
});
@ -147,15 +159,18 @@ void ViewFile(){
case MenuSaveMedia:
if (IsVideo){
control.InvokeAsyncSafe(analytics.AnalyticsFile.CountDownloadedVideos.Trigger);
TwitterUtils.DownloadVideo(GetMediaLink(parameters), lastHighlightedTweetAuthors.LastOrDefault());
}
else{
control.InvokeAsyncSafe(analytics.AnalyticsFile.CountDownloadedImages.Trigger);
TwitterUtils.DownloadImage(GetMediaLink(parameters), lastHighlightedTweetAuthors.LastOrDefault(), ImageQuality);
}
break;
case MenuSaveTweetImages:
control.InvokeAsyncSafe(analytics.AnalyticsFile.CountDownloadedImages.Trigger);
TwitterUtils.DownloadImages(lastHighlightedTweetImageList, lastHighlightedTweetAuthors.LastOrDefault(), ImageQuality);
break;

View File

@ -30,7 +30,7 @@ sealed class ContextMenuBrowser : ContextMenuBase{
private string lastHighlightedTweetUrl;
private string lastHighlightedQuoteUrl;
public ContextMenuBrowser(FormBrowser form){
public ContextMenuBrowser(FormBrowser form) : base(form){
this.form = form;
}

View File

@ -1,7 +1,10 @@
using CefSharp;
using TweetDuck.Core.Other.Analytics;
namespace TweetDuck.Core.Handling{
sealed class ContextMenuGuide : ContextMenuBase{
public ContextMenuGuide(AnalyticsFile.IProvider analytics) : base(analytics){}
public override void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model){
model.Clear();
base.OnBeforeContextMenu(browserControl, browser, frame, parameters, model);

View File

@ -13,7 +13,7 @@ sealed class ContextMenuNotification : ContextMenuBase{
private readonly FormNotificationBase form;
private readonly bool enableCustomMenu;
public ContextMenuNotification(FormNotificationBase form, bool enableCustomMenu){
public ContextMenuNotification(FormNotificationBase form, bool enableCustomMenu) : base(form){
this.form = form;
this.enableCustomMenu = enableCustomMenu;
}

View File

@ -22,7 +22,7 @@ public bool Running{
public event EventHandler ProcessExited;
private readonly Form owner;
private readonly FormBrowser owner;
private string lastUrl;
private string lastUsername;
@ -30,7 +30,7 @@ public bool Running{
private DuplexPipe.Server currentPipe;
private bool isClosing;
public VideoPlayer(Form owner){
public VideoPlayer(FormBrowser owner){
this.owner = owner;
this.owner.FormClosing += owner_FormClosing;
}
@ -83,6 +83,7 @@ private void currentPipe_DataIn(object sender, DuplexPipe.PipeReadEventArgs e){
break;
case "download":
owner.AnalyticsFile.CountDownloadedVideos.Trigger();
TwitterUtils.DownloadVideo(lastUrl, lastUsername);
break;

View File

@ -12,7 +12,7 @@
using TweetDuck.Core.Utils;
namespace TweetDuck.Core.Notification{
partial class FormNotificationBase : Form{
partial class FormNotificationBase : Form, AnalyticsFile.IProvider{
protected static int FontSizeLevel{
get{
switch(TweetDeckBridge.FontSize){

View File

@ -46,6 +46,12 @@ static AnalyticsFile(){
public Counter CountNotificationExtraMouseButtons { get; private set; } = 0;
public Counter CountNotificationKeyboardShortcuts { get; private set; } = 0;
public Counter CountBrowserReloads { get; private set; } = 0;
public Counter CountCopiedUsernames { get; private set; } = 0;
public Counter CountViewedImages { get; private set; } = 0;
public Counter CountDownloadedImages { get; private set; } = 0;
public Counter CountDownloadedVideos { get; private set; } = 0;
public Counter CountUsedROT13 { get; private set; } = 0;
public Counter CountTweetScreenshots { get; private set; } = 0;
public Counter CountTweetDetails { get; private set; } = 0;
@ -96,6 +102,10 @@ public static AnalyticsFile Load(string file){
return config;
}
public interface IProvider{
AnalyticsFile AnalyticsFile { get; }
}
public sealed class Counter{
public int Value { get; private set; }

View File

@ -8,7 +8,7 @@
namespace TweetDuck.Core.Other.Analytics{
sealed class AnalyticsManager : IDisposable{
private static readonly TimeSpan CollectionInterval = TimeSpan.FromDays(7);
private static readonly TimeSpan CollectionInterval = TimeSpan.FromDays(14);
private static readonly Uri CollectionUrl = new Uri("https://tweetduck.chylex.com/breadcrumb/report");
public AnalyticsFile File { get; }

View File

@ -12,6 +12,7 @@
using TweetDuck.Core.Notification;
using TweetDuck.Core.Utils;
using TweetDuck.Plugins;
using TweetDuck.Plugins.Enums;
namespace TweetDuck.Core.Other.Analytics{
static class AnalyticsReportGenerator{
@ -36,15 +37,24 @@ public static AnalyticsReport Create(AnalyticsFile file, ExternalInfo info, Plug
{ "Screen Resolution" , info.Resolution ?? "(unknown)" },
{ "Screen DPI" , info.DPI != null ? Exact(info.DPI.Value) : "(unknown)" },
0,
{ "Hardware Acceleration" , Bool(SysConfig.HardwareAcceleration) },
{ "Hardware Acceleration" , Bool(SysConfig.HardwareAcceleration) },
{ "Clear Cache Automatically" , Bool(SysConfig.ClearCacheAutomatically) },
{ "Clear Cache Threshold" , Exact(SysConfig.ClearCacheThreshold) },
0,
{ "Expand Links" , Bool(UserConfig.ExpandLinksOnHover) },
{ "Switch Account Selectors" , Bool(UserConfig.SwitchAccountSelectors) },
{ "Search In First Column" , Bool(UserConfig.OpenSearchInFirstColumn) },
{ "Keep Like Follow Dialogs Open" , Bool(UserConfig.KeepLikeFollowDialogsOpen) },
{ "Best Image Quality" , Bool(UserConfig.BestImageQuality) },
{ "Spell Check" , Bool(UserConfig.EnableSpellCheck) },
{ "Zoom" , Exact(UserConfig.ZoomLevel) },
{ "Animated Images" , Bool(UserConfig.EnableAnimatedImages) },
0,
{ "Smooth Scrolling" , Bool(UserConfig.EnableSmoothScrolling) },
{ "Custom Browser" , CustomBrowser },
{ "Zoom" , Exact(UserConfig.ZoomLevel) },
0,
{ "Spell Check" , Bool(UserConfig.EnableSpellCheck) },
{ "Spell Check Language" , UserConfig.SpellCheckLanguage.ToLower() },
{ "Translation Target Language" , UserConfig.TranslationTarget },
0,
{ "Updates" , Bool(UserConfig.EnableUpdateCheck) },
{ "Update Dismissed" , Bool(!string.IsNullOrEmpty(UserConfig.DismissedUpdate)) },
@ -70,8 +80,8 @@ public static AnalyticsReport Create(AnalyticsFile file, ExternalInfo info, Plug
{ "Custom Browser CSS" , RoundUp((UserConfig.CustomBrowserCSS ?? string.Empty).Length, 50) },
{ "Custom Notification CSS" , RoundUp((UserConfig.CustomNotificationCSS ?? string.Empty).Length, 50) },
0,
{ "Plugins All" , List(plugins.Plugins.Select(plugin => plugin.Identifier)) },
{ "Plugins Enabled" , List(plugins.Plugins.Where(plugin => plugins.Config.IsEnabled(plugin)).Select(plugin => plugin.Identifier)) },
{ "Plugins All" , List(plugins.Plugins.Select(Plugin)) },
{ "Plugins Enabled" , List(plugins.Plugins.Where(plugin => plugins.Config.IsEnabled(plugin)).Select(Plugin)) },
0,
{ "Theme" , Dict(editLayoutDesign, "_theme", "light/def") },
{ "Column Width" , Dict(editLayoutDesign, "columnWidth", "310px/def") },
@ -99,6 +109,12 @@ public static AnalyticsReport Create(AnalyticsFile file, ExternalInfo info, Plug
{ "Notification Context Menus" , LogRound(file.CountNotificationContextMenus, 2) },
{ "Notification Extra Mouse Buttons" , LogRound(file.CountNotificationExtraMouseButtons, 2) },
{ "Notification Keyboard Shortcuts" , LogRound(file.CountNotificationKeyboardShortcuts, 2) },
{ "Browser Reloads" , LogRound(file.CountBrowserReloads, 2) },
{ "Copied Usernames" , LogRound(file.CountCopiedUsernames, 2) },
{ "Viewed Images" , LogRound(file.CountViewedImages, 2) },
{ "Downloaded Images" , LogRound(file.CountDownloadedImages, 2) },
{ "Downloaded Videos" , LogRound(file.CountDownloadedVideos, 2) },
{ "Used ROT13" , LogRound(file.CountUsedROT13, 2) },
{ "Tweet Screenshots" , LogRound(file.CountTweetScreenshots, 2) },
{ "Tweet Details" , LogRound(file.CountTweetDetails, 2) },
{ "Video Plays" , LogRound(file.CountVideoPlays, 4) }
@ -112,6 +128,7 @@ public static AnalyticsReport Create(AnalyticsFile file, ExternalInfo info, Plug
private static string Exact(int value) => value.ToString();
private static string RoundUp(int value, int multiple) => (multiple*(int)Math.Ceiling((double)value/multiple)).ToString();
private static string LogRound(int value, int logBase) => (value <= 0 ? 0 : (int)Math.Pow(logBase, Math.Floor(Math.Log(value, logBase)))).ToString();
private static string Plugin(Plugin plugin) => plugin.Group.GetIdentifierPrefixShort()+plugin.Identifier.Substring(plugin.Group.GetIdentifierPrefix().Length);
private static string Dict(Dictionary<string, string> dict, string key, string def = "(unknown)") => dict.TryGetValue(key, out string value) ? value : def;
private static string List(IEnumerable<string> list) => string.Join("|", list.DefaultIfEmpty("(none)"));
@ -182,6 +199,12 @@ static AnalyticsReportGenerator(){
ProgramArguments = args.Keys.Select(key => key.TrimStart('-')).ToArray();
}
private static string CustomBrowser{
get{
return Path.GetFileName(UserConfig.BrowserPath) ?? string.Empty;
}
}
private static string TrayMode{
get{
switch(UserConfig.TrayBehavior){

View File

@ -54,7 +54,7 @@ public static void Show(string hash = null){
private readonly ChromiumWebBrowser browser;
private FormGuide(string url, Form owner){
private FormGuide(string url, FormBrowser owner){
InitializeComponent();
Text = Program.BrandName+" Guide";
@ -65,7 +65,7 @@ private FormGuide(string url, Form owner){
}
this.browser = new ChromiumWebBrowser(url){
MenuHandler = new ContextMenuGuide(),
MenuHandler = new ContextMenuGuide(owner),
JsDialogHandler = new JavaScriptDialogHandler(),
LifeSpanHandler = new LifeSpanHandler(),
RequestHandler = new RequestHandlerBrowser()

View File

@ -11,5 +11,13 @@ public static string GetIdentifierPrefix(this PluginGroup group){
default: return "unknown/";
}
}
public static string GetIdentifierPrefixShort(this PluginGroup group){
switch(group){
case PluginGroup.Official: return "o/";
case PluginGroup.Custom: return "c/";
default: return "?/";
}
}
}
}