diff --git a/src/Host.h b/src/Host.h index 6def17558..43207a275 100644 --- a/src/Host.h +++ b/src/Host.h @@ -683,7 +683,6 @@ public: QMap profileShortcuts; bool mTutorialForCompactLineAlreadyShown; - bool mTutorialForSplitscreenScrollbackAlreadyShown = false; bool mAnnounceIncomingText = true; bool mAdvertiseScreenReader = false; diff --git a/src/TConsole.cpp b/src/TConsole.cpp index 3581c6ae2..2c15b1e0d 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -1023,14 +1023,14 @@ void TConsole::scrollUp(int lines) if (lowerAppears) { QTimer::singleShot(0, this, [this]() { mUpperPane->scrollUp(mLowerPane->getRowCount()); }); - if (!mpHost->mTutorialForSplitscreenScrollbackAlreadyShown) { + if (mudlet::self()->showSplitscreenTutorial()) { #if defined(Q_OS_MACOS) const QString infoMsg = tr("[ INFO ] - Split-screen scrollback activated. Press <⌘>+ to cancel."); #else const QString infoMsg = tr("[ INFO ] - Split-screen scrollback activated. Press + to cancel."); #endif mpHost->postMessage(infoMsg); - mpHost->mTutorialForSplitscreenScrollbackAlreadyShown = true; + mudlet::self()->showedSplitscreenTutorial(); } } mUpperPane->scrollUp(lines); diff --git a/src/mudlet.cpp b/src/mudlet.cpp index bda23b334..9bdeb6117 100644 --- a/src/mudlet.cpp +++ b/src/mudlet.cpp @@ -1960,6 +1960,7 @@ void mudlet::readLateSettings(const QSettings& settings) setToolBarIconSize(settings.value(qsl("mainiconsize")).toInt()); } setEditorTreeWidgetIconSize(settings.value("tefoldericonsize", QVariant(3)).toInt()); + mScrollbackTutorialsShown = settings.value("scrollbackTutorialsShown", QVariant(0)).toInt(); // We have abandoned previous "showMenuBar" / "showToolBar" booleans // although we provide a backwards compatible value // of: (bool) showXXXXBar = (XXXXBarVisibilty != visibleNever) for, until, @@ -2109,6 +2110,7 @@ void mudlet::writeSettings() settings.setValue("size", size()); settings.setValue("mainiconsize", mToolbarIconSize); settings.setValue("tefoldericonsize", mEditorTreeWidgetIconSize); + settings.setValue("scrollbackTutorialsShown", mScrollbackTutorialsShown); // This pair are only for backwards compatibility and will be ignored for // this and future Mudlet versions - suggest they get removed in Mudlet 4.x settings.setValue("showMenuBar", mMenuBarVisibility != visibleNever); @@ -4981,6 +4983,40 @@ void mudlet::armForceClose() }); } +bool mudlet::showSplitscreenTutorial() +{ + return !experiencedMudletPlayer() && mScrollbackTutorialsShown < mScrollbackTutorialsMax; +} + +void mudlet::showedSplitscreenTutorial() +{ + mScrollbackTutorialsShown++; +} + +// returns true if the Mudlet player is considered 'experienced' and doesn't need to be shown the basic +// tutorial tips, such as splitscreen cancel shortcut +bool mudlet::experiencedMudletPlayer() +{ + static std::optional cachedResult; + if (cachedResult.has_value()) { + return cachedResult.value(); + } + + // crude metric to check if the player is experienced in Mudlet: see if any of the profiles is more than 6mo old + QDir profilesDir(mudlet::getMudletPath(mudlet::profilesPath)); + QFileInfoList entries = profilesDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + QDateTime sixMonthsAgo = QDateTime::currentDateTime().addMonths(-6); + + for (const QFileInfo &entry : entries) { + if (entry.lastModified() < sixMonthsAgo) { + cachedResult = true; + return true; + } + } + cachedResult = false; + return false; +} + dlgTriggerEditor* mudlet::createMudletEditor() { Host* pHost = getActiveHost(); diff --git a/src/mudlet.h b/src/mudlet.h index 68cc6edf2..e0458ec97 100644 --- a/src/mudlet.h +++ b/src/mudlet.h @@ -418,6 +418,9 @@ public: bool muteGame() const { return mMuteGame; } bool mediaMuted() const { return mMuteAPI && mMuteGame; } bool mediaUnmuted() const { return !mMuteAPI && !mMuteGame; } + auto showSplitscreenTutorial() -> bool; + auto showedSplitscreenTutorial() -> void; + auto experiencedMudletPlayer() -> bool; Appearance mAppearance = Appearance::systemSetting; // 1 (of 2) needed to work around a (Windows/MacOs specific QStyleFactory) @@ -426,6 +429,7 @@ public: // approximate max duration that 'Copy as image' is allowed to take // (seconds): int mCopyAsImageTimeout = 3; + // A list of potential dictionary languages - probably will cover a much // wider range of languages compared to the translations - and is intended // for Dictionary identification - there is a request for users to submit @@ -738,6 +742,11 @@ private: QMap mUserToolbarMap; // The collection of words in what mpHunspell_sharedDictionary points to: QSet mWordSet_shared; + + // amount of times the shortcut to cancel split screen has been shown help educate new users + int mScrollbackTutorialsShown = 0; + // show the split screen tutorial maximum 3 times on a new Mudlet + static const int mScrollbackTutorialsMax = 3; }; Q_DECLARE_OPERATORS_FOR_FLAGS(mudlet::controlsVisibility)