diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index d08d5824d23d51..f1ea2ce849a93d 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -3,51 +3,50 @@ name: Windows. on: push: paths-ignore: - - 'docs/**' - - '**.md' - - 'changelog.txt' - - 'LEGAL' - - 'LICENSE' - - '.github/**' - - '!.github/workflows/win.yml' - - 'lib/xdg/**' - - 'snap/**' - - 'Telegram/build/docker/**' - - 'Telegram/Resources/uwp/**' - - 'Telegram/SourceFiles/platform/linux/**' - - 'Telegram/SourceFiles/platform/mac/**' - - 'Telegram/Telegram/**' - - 'Telegram/configure.sh' - - 'Telegram/Telegram.plist' + - "docs/**" + - "**.md" + - "changelog.txt" + - "LEGAL" + - "LICENSE" + - ".github/**" + - "!.github/workflows/win.yml" + - "lib/xdg/**" + - "snap/**" + - "Telegram/build/docker/**" + - "Telegram/Resources/uwp/**" + - "Telegram/SourceFiles/platform/linux/**" + - "Telegram/SourceFiles/platform/mac/**" + - "Telegram/Telegram/**" + - "Telegram/configure.sh" + - "Telegram/Telegram.plist" pull_request: paths-ignore: - - 'docs/**' - - '**.md' - - 'changelog.txt' - - 'LEGAL' - - 'LICENSE' - - '.github/**' - - '!.github/workflows/win.yml' - - 'lib/xdg/**' - - 'snap/**' - - 'Telegram/build/docker/**' - - 'Telegram/Resources/uwp/**' - - 'Telegram/SourceFiles/platform/linux/**' - - 'Telegram/SourceFiles/platform/mac/**' - - 'Telegram/Telegram/**' - - 'Telegram/configure.sh' - - 'Telegram/Telegram.plist' + - "docs/**" + - "**.md" + - "changelog.txt" + - "LEGAL" + - "LICENSE" + - ".github/**" + - "!.github/workflows/win.yml" + - "lib/xdg/**" + - "snap/**" + - "Telegram/build/docker/**" + - "Telegram/Resources/uwp/**" + - "Telegram/SourceFiles/platform/linux/**" + - "Telegram/SourceFiles/platform/mac/**" + - "Telegram/Telegram/**" + - "Telegram/configure.sh" + - "Telegram/Telegram.plist" jobs: - windows: name: Windows runs-on: windows-latest strategy: matrix: - arch: [Win32, x64] - generator: ["", "Ninja Multi-Config"] + arch: [x64] + generator: [""] env: UPLOAD_ARTIFACT: "true" @@ -116,7 +115,7 @@ jobs: GYP_MSVS_VERSION: 2022 run: | cd %TBUILD% - %REPO_NAME%\Telegram\build\prepare\win.bat skip-release silent + %REPO_NAME%\Telegram\build\prepare\win.bat silent - name: Read configuration matrix. shell: bash @@ -176,23 +175,22 @@ jobs: call configure.bat ^ %TDESKTOP_BUILD_GENERATOR% ^ %TDESKTOP_BUILD_ARCH% ^ - %TDESKTOP_BUILD_API% ^ + -D TDESKTOP_API_ID=17349 -D TDESKTOP_API_HASH=344583e45741c457fe1862106095a5eb ^ -D CMAKE_C_FLAGS="/WX" ^ -D CMAKE_CXX_FLAGS="/WX" ^ - -D DESKTOP_APP_DISABLE_AUTOUPDATE=OFF ^ - -D DESKTOP_APP_DISABLE_CRASH_REPORTS=OFF ^ + -D DESKTOP_APP_DISABLE_AUTOUPDATE=ON ^ + -D DESKTOP_APP_DISABLE_CRASH_REPORTS=ON ^ -D DESKTOP_APP_NO_PDB=ON ^ %TDESKTOP_BUILD_DEFINE% - cmake --build ..\out --config Debug --parallel + cmake --build ..\out --config Release --parallel - name: Move artifact. if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly') run: | - set OUT=%TBUILD%\%REPO_NAME%\out\Debug + set OUT=%TBUILD%\%REPO_NAME%\out\Release mkdir artifact move %OUT%\Telegram.exe artifact/ - move %OUT%\Updater.exe artifact/ - uses: actions/upload-artifact@v4 name: Upload artifact. if: (env.UPLOAD_ARTIFACT == 'true') || (github.ref == 'refs/heads/nightly') diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 5d4370b535a294..534da1c9a3a468 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3984,6 +3984,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_context_copy_image" = "Copy Image"; "lng_context_cancel_download" = "Cancel Download"; "lng_context_show_in_folder" = "Show in Folder"; +"lng_context_open_extra" = "外部播放器"; "lng_context_show_in_finder" = "Show in Finder"; "lng_context_save_video" = "Save As..."; "lng_context_save_audio_file" = "Save As..."; diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index c6befff047332c..df94b2ca96c70c 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -90,6 +90,7 @@ void UpdateStickerSetIdentifier( } // namespace +//得到合法的文件名 QString FileNameUnsafe( not_null session, const QString &title, @@ -173,6 +174,8 @@ QString FileNameUnsafe( } QString nameBase = path + nameStart; name = nameBase + extension; + + //遍历文件是不是存在 否则加(2) for (int i = 0; QFileInfo::exists(name); ++i) { name = nameBase + u" (%1)"_q.arg(i + 2) + extension; } @@ -1323,6 +1326,7 @@ QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform) { return result; } +//文件位置 未来可能需要hack const Core::FileLocation &DocumentData::location(bool check) const { if (check && !_location.check()) { const auto location = session().local().readFileLocation(mediaKey()); @@ -1332,6 +1336,73 @@ const Core::FileLocation &DocumentData::location(bool check) const { } else { that->_location = location; } + + //如果本地文件不存在,则去另外的地方拿 + if (location.isEmpty()) + { + const auto filepath = this->filepath(true); + const auto fileinfo = QFileInfo(); + const auto filedir = filepath.isEmpty() + ? QDir() + : fileinfo.dir(); + const auto filename = filepath.isEmpty() + ? QString() + : fileinfo.fileName(); + + //文件路径 + const auto savename = DocumentFileNameForSave( + this, + false, + filename, + filedir); + + // 分离文件路径的目录、文件名和扩展名 + QFileInfo fileInfo(savename); + QString baseName = fileInfo.baseName(); // 文件名(不含扩展名) + QString suffix = fileInfo.suffix(); // 扩展名 + QString path = fileInfo.path(); // 文件路径 + + // 使用正则表达式移除文件名末尾的 (数字) 部分 + QRegularExpression regex("\\s\\(\\d+\\)$"); + QString cleanedBaseName = baseName.replace(regex, ""); + + qDebug() << this->id; + + qDebug() << "清理后的文件名:" << cleanedBaseName; + + // 拼接清理后的文件名和扩展名 + const QString nameBase = cleanedBaseName; + + const auto fileSize = this->size; + + // 定义一个 QStringList,相当于 JavaScript 中的数组 + QStringList pathArr; + pathArr << path << "Z:\\tgfiles\\account\\a402dae4-8dce-4e32-b8c8-9994d154bb2d\\videos"; // 使用 << 操作符添加元素 + + // 使用基于范围的 for 循环遍历 QStringList + for (const QString& path : pathArr) { + + for (size_t i = 0; i < 5; i++) + { + QString fileName; + if (i == 0) + { + fileName = path + "\\" + nameBase + "." + suffix; + } + else + { + fileName = path + "\\" + nameBase + u" (%1)."_q.arg(i + 1) + suffix; + } + + qDebug() << fileName; + + if (QFileInfo fi(fileName); fi.exists() && fi.size() == fileSize) + { + return Core::FileLocation(filename); + } + } + } + } } return _location; } diff --git a/Telegram/SourceFiles/data/data_document_resolver.cpp b/Telegram/SourceFiles/data/data_document_resolver.cpp index 4c901daa24eb05..58fadcc7c8096f 100644 --- a/Telegram/SourceFiles/data/data_document_resolver.cpp +++ b/Telegram/SourceFiles/data/data_document_resolver.cpp @@ -7,6 +7,9 @@ For license and copyright information please follow this link: */ #include "data/data_document_resolver.h" +#include +#include + #include "base/options.h" #include "base/platform/base_platform_info.h" #include "boxes/abstract_box.h" // Ui::show(). @@ -36,235 +39,328 @@ For license and copyright information please follow this link: #include #include -namespace Data { -namespace { +#include "data_channel.h" + +namespace Data +{ + namespace + { + base::options::toggle OptionExternalVideoPlayer({ + .id = kOptionExternalVideoPlayer, + .name = "External video player", + .description = "Use system video player instead of the internal one. " + "This disabes video playback in messages.", + }); + + void ConfirmDontWarnBox( + not_null box, + rpl::producer&& text, + rpl::producer&& check, + rpl::producer&& confirm, + Fn callback) + { + auto checkbox = object_ptr( + box.get(), + std::move(check), + false, + st::defaultBoxCheckbox); + const auto weak = Ui::MakeWeak(checkbox.data()); + auto confirmed = crl::guard(weak, [=, callback = std::move(callback)] + { + const auto checked = weak->checked(); + box->closeBox(); + callback(checked); + }); + Ui::ConfirmBox(box, { + .text = std::move(text), + .confirmed = std::move(confirmed), + .confirmText = std::move(confirm), + }); + auto padding = st::boxPadding; + padding.setTop(padding.bottom()); + box->addRow(std::move(checkbox), std::move(padding)); + box->addRow(object_ptr>( + box, + object_ptr( + box, + tr::lng_launch_dont_ask_settings(), + st::boxLabel) + ))->toggleOn(weak->checkedValue()); + } + + void LaunchWithWarning( + // not_null controller, + const QString& name, + HistoryItem* item) + { + const auto nameType = Core::DetectNameType(name); + const auto isIpReveal = (nameType != Core::NameType::Executable) + && Core::IsIpRevealingPath(name); + const auto extension = Core::FileExtension(name).toLower(); + + auto& app = Core::App(); + auto& settings = app.settings(); + const auto warn = [&] + { + if (item && item->history()->peer->isVerified()) + { + return false; + } + return (isIpReveal && settings.ipRevealWarning()) + || ((nameType == Core::NameType::Executable + || nameType == Core::NameType::Unknown) + && !settings.noWarningExtensions().contains(extension)); + }(); + if (extension.isEmpty()) + { + // If you launch a file without extension, like "test", in case + // there is an executable file with the same name in this folder, + // like "test.bat", the executable file will be launched. + // + // Now we always force an Open With dialog box for such files. + // + // Let's force it for all platforms for files without extension. + crl::on_main([=] + { + Platform::File::UnsafeShowOpenWith(name); + }); + return; + } + else if (!warn) + { + File::Launch(name); + return; + } + const auto callback = [=, &app, &settings](bool checked) + { + if (checked) + { + if (isIpReveal) + { + settings.setIpRevealWarning(false); + } + else + { + auto copy = settings.noWarningExtensions(); + copy.emplace(extension); + settings.setNoWarningExtensions(std::move(copy)); + } + app.saveSettingsDelayed(); + } + File::Launch(name); + }; + auto text = isIpReveal + ? tr::lng_launch_svg_warning(Ui::Text::WithEntities) + : ((nameType == Core::NameType::Executable) + ? tr::lng_launch_exe_warning + : tr::lng_launch_other_warning)( + lt_extension, + rpl::single(Ui::Text::Bold('.' + extension)), + Ui::Text::WithEntities); + auto check = (isIpReveal + ? tr::lng_launch_exe_dont_ask + : tr::lng_launch_dont_ask)(); + auto confirm = ((nameType == Core::NameType::Executable) + ? tr::lng_launch_exe_sure + : tr::lng_launch_other_sure)(); + Ui::show(Box( + ConfirmDontWarnBox, + std::move(text), + std::move(check), + std::move(confirm), + callback)); + } + } // namespace + + const char kOptionExternalVideoPlayer[] = "external-video-player"; + + base::binary_guard ReadBackgroundImageAsync( + not_null media, + FnMut postprocess, + FnMut done) + { + auto result = base::binary_guard(); + const auto gzipSvg = media->owner()->isPatternWallPaperSVG(); + crl::async([ + gzipSvg, + bytes = media->bytes(), + path = media->owner()->filepath(), + postprocess = std::move(postprocess), + guard = result.make_guard(), + callback = std::move(done) + ]() mutable + { + auto image = Ui::ReadBackgroundImage(path, bytes, gzipSvg); + if (postprocess) + { + image = postprocess(std::move(image)); + } + crl::on_main(std::move(guard), [ + image = std::move(image), + callback = std::move(callback) + ]() mutable + { + callback(std::move(image)); + }); + }); + return result; + } + + /** + * @brief 检查应用程序根目录下的 url.txt 文件并读取其内容。 + * @return 如果文件存在且读取成功,返回文件内容的 QString;否则返回一个空 QString。 + */ + QString GetBaseUrl() + { + // 1. 构建文件的完整路径 + // QCoreApplication::applicationDirPath() 获取可执行文件所在的目录 + QString filePath = QCoreApplication::applicationDirPath() + "/url.txt"; + + // 2. 创建 QFile 对象 + QFile file(filePath); + + // 3. 检查文件是否存在,并且是否能以只读、文本模式成功打开 + if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + // 4. 创建 QTextStream 以便方便地读取文本 + QTextStream in(&file); -base::options::toggle OptionExternalVideoPlayer({ - .id = kOptionExternalVideoPlayer, - .name = "External video player", - .description = "Use system video player instead of the internal one. " - "This disabes video playback in messages.", -}); + // 建议设置编码,以防URL或文件中包含非ASCII字符导致乱码 + in.setCodec("UTF-8"); -void ConfirmDontWarnBox( - not_null box, - rpl::producer &&text, - rpl::producer &&check, - rpl::producer &&confirm, - Fn callback) { - auto checkbox = object_ptr( - box.get(), - std::move(check), - false, - st::defaultBoxCheckbox); - const auto weak = Ui::MakeWeak(checkbox.data()); - auto confirmed = crl::guard(weak, [=, callback = std::move(callback)] { - const auto checked = weak->checked(); - box->closeBox(); - callback(checked); - }); - Ui::ConfirmBox(box, { - .text = std::move(text), - .confirmed = std::move(confirmed), - .confirmText = std::move(confirm), - }); - auto padding = st::boxPadding; - padding.setTop(padding.bottom()); - box->addRow(std::move(checkbox), std::move(padding)); - box->addRow(object_ptr>( - box, - object_ptr( - box, - tr::lng_launch_dont_ask_settings(), - st::boxLabel) - ))->toggleOn(weak->checkedValue()); -} + // 5. 读取文件的全部内容 + QString content = in.readAll(); -void LaunchWithWarning( - // not_null controller, - const QString &name, - HistoryItem *item) { - const auto nameType = Core::DetectNameType(name); - const auto isIpReveal = (nameType != Core::NameType::Executable) - && Core::IsIpRevealingPath(name); - const auto extension = Core::FileExtension(name).toLower(); + // QFile 对象在析构时会自动关闭文件,但显式调用 close() 是个好习惯 + file.close(); - auto &app = Core::App(); - auto &settings = app.settings(); - const auto warn = [&] { - if (item && item->history()->peer->isVerified()) { - return false; - } - return (isIpReveal && settings.ipRevealWarning()) - || ((nameType == Core::NameType::Executable - || nameType == Core::NameType::Unknown) - && !settings.noWarningExtensions().contains(extension)); - }(); - if (extension.isEmpty()) { - // If you launch a file without extension, like "test", in case - // there is an executable file with the same name in this folder, - // like "test.bat", the executable file will be launched. - // - // Now we always force an Open With dialog box for such files. - // - // Let's force it for all platforms for files without extension. - crl::on_main([=] { - Platform::File::UnsafeShowOpenWith(name); - }); - return; - } else if (!warn) { - File::Launch(name); - return; - } - const auto callback = [=, &app, &settings](bool checked) { - if (checked) { - if (isIpReveal) { - settings.setIpRevealWarning(false); - } else { - auto copy = settings.noWarningExtensions(); - copy.emplace(extension); - settings.setNoWarningExtensions(std::move(copy)); - } - app.saveSettingsDelayed(); - } - File::Launch(name); - }; - auto text = isIpReveal - ? tr::lng_launch_svg_warning(Ui::Text::WithEntities) - : ((nameType == Core::NameType::Executable) - ? tr::lng_launch_exe_warning - : tr::lng_launch_other_warning)( - lt_extension, - rpl::single(Ui::Text::Bold('.' + extension)), - Ui::Text::WithEntities); - auto check = (isIpReveal - ? tr::lng_launch_exe_dont_ask - : tr::lng_launch_dont_ask)(); - auto confirm = ((nameType == Core::NameType::Executable) - ? tr::lng_launch_exe_sure - : tr::lng_launch_other_sure)(); - Ui::show(Box( - ConfirmDontWarnBox, - std::move(text), - std::move(check), - std::move(confirm), - callback)); -} + // 6. 返回读取到的内容 + return content; + } -} // namespace + // 7. 如果文件不存在或打开失败,返回一个默认构造的空 QString + return QString(); + } -const char kOptionExternalVideoPlayer[] = "external-video-player"; + void ResolveDocument( + Window::SessionController* controller, + not_null document, + HistoryItem* item, + MsgId topicRootId) + { + if (document->isNull()) + { + return; + } + const auto msgId = item ? item->fullId() : FullMsgId(); -base::binary_guard ReadBackgroundImageAsync( - not_null media, - FnMut postprocess, - FnMut done) { - auto result = base::binary_guard(); - const auto gzipSvg = media->owner()->isPatternWallPaperSVG(); - crl::async([ - gzipSvg, - bytes = media->bytes(), - path = media->owner()->filepath(), - postprocess = std::move(postprocess), - guard = result.make_guard(), - callback = std::move(done) - ]() mutable { - auto image = Ui::ReadBackgroundImage(path, bytes, gzipSvg); - if (postprocess) { - image = postprocess(std::move(image)); - } - crl::on_main(std::move(guard), [ - image = std::move(image), - callback = std::move(callback) - ]() mutable { - callback(std::move(image)); - }); - }); - return result; -} + qDebug() << msgId.peer.value; + qDebug() << msgId.msg.bare; -void ResolveDocument( - Window::SessionController *controller, - not_null document, - HistoryItem *item, - MsgId topicRootId) { - if (document->isNull()) { - return; - } - const auto msgId = item ? item->fullId() : FullMsgId(); - const auto showDocument = [&] { - if (OptionExternalVideoPlayer.value() - && document->isVideoFile() - && !document->filepath().isEmpty()) { - File::Launch(document->location(false).fname); - } else if (controller) { - controller->openDocument( - document, - true, - { msgId, topicRootId }); - } - }; + const auto showDocument = [&] + { + if ((true || OptionExternalVideoPlayer.value()) //在文件下载完成后,可以直接使用外部播放器打开 + && document->isVideoFile() + && !document->filepath().isEmpty()) + { + File::Launch(document->location(false).fname); + } + else if (controller) + { + controller->openDocument( + document, + true, + {msgId, topicRootId}); + } + }; - const auto media = document->createMediaView(); - const auto openImageInApp = [&] { - if (document->size >= Images::kReadBytesLimit) { - return false; - } - const auto &location = document->location(true); - const auto mime = u"image/"_q; - if (!location.isEmpty() && location.accessEnable()) { - const auto guard = gsl::finally([&] { - location.accessDisable(); - }); - const auto path = location.name(); - if (Core::MimeTypeForFile(QFileInfo(path)).name().startsWith(mime) - && QImageReader(path).canRead()) { - showDocument(); - return true; - } - } else if (document->mimeString().startsWith(mime) - && !media->bytes().isEmpty()) { - auto bytes = media->bytes(); - auto buffer = QBuffer(&bytes); - if (QImageReader(&buffer).canRead()) { - showDocument(); - return true; - } - } - return false; - }; - const auto &location = document->location(true); - if (document->isTheme() && media->loaded(true)) { - showDocument(); - location.accessDisable(); - } else if (media->canBePlayed(item)) { - if (document->isAudioFile() - || document->isVoiceMessage() - || document->isVideoMessage()) { - ::Media::Player::instance()->playPause({ document, msgId }); - if (controller - && item - && item->media() - && item->media()->ttlSeconds()) { - ChatHelpers::ShowTTLMediaLayerWidget(controller, item); - } - } else { - showDocument(); - } - } else { - document->saveFromDataSilent(); - if (!openImageInApp()) { - if (!document->filepath(true).isEmpty()) { - LaunchWithWarning(location.name(), item); - } else if (document->status == FileReady - || document->status == FileDownloadFailed) { - DocumentSaveClickHandler::Save( - item ? item->fullId() : Data::FileOrigin(), - document); - } - } - } -} + const auto media = document->createMediaView(); + const auto openImageInApp = [&] + { + if (document->size >= Images::kReadBytesLimit) + { + return false; + } + const auto& location = document->location(true); + const auto mime = u"image/"_q; + if (!location.isEmpty() && location.accessEnable()) + { + const auto guard = gsl::finally([&] + { + location.accessDisable(); + }); + const auto path = location.name(); + if (Core::MimeTypeForFile(QFileInfo(path)).name().startsWith(mime) + && QImageReader(path).canRead()) + { + showDocument(); + return true; + } + } + else if (document->mimeString().startsWith(mime) + && !media->bytes().isEmpty()) + { + auto bytes = media->bytes(); + auto buffer = QBuffer(&bytes); + if (QImageReader(&buffer).canRead()) + { + showDocument(); + return true; + } + } + return false; + }; + const auto& location = document->location(true); + if (document->isTheme() && media->loaded(true)) + { + showDocument(); + location.accessDisable(); + } + else if (media->canBePlayed(item)) + { + if (document->isAudioFile() + || document->isVoiceMessage() + || document->isVideoMessage()) + { + ::Media::Player::instance()->playPause({document, msgId}); + if (controller + && item + && item->media() + && item->media()->ttlSeconds()) + { + ChatHelpers::ShowTTLMediaLayerWidget(controller, item); + } + } + else + { + //if (document->size > (150 * 1024 * 10240)) + showDocument(); + // QTimer::singleShot(1000, [item,document]() { + // DocumentSaveClickHandler::Save( + // item ? item->fullId() : Data::FileOrigin(), + // document); + // }); + } + } + else + { + document->saveFromDataSilent(); + if (!openImageInApp()) + { + if (!document->filepath(true).isEmpty()) + { + LaunchWithWarning(location.name(), item); + } + else if (document->status == FileReady + || document->status == FileDownloadFailed) + { + DocumentSaveClickHandler::Save( + item ? item->fullId() : Data::FileOrigin(), + document); + } + } + } + } } // namespace Data diff --git a/Telegram/SourceFiles/data/data_file_click_handler.cpp b/Telegram/SourceFiles/data/data_file_click_handler.cpp index e42397d197e112..475f9bf547bad8 100644 --- a/Telegram/SourceFiles/data/data_file_click_handler.cpp +++ b/Telegram/SourceFiles/data/data_file_click_handler.cpp @@ -15,6 +15,8 @@ For license and copyright information please follow this link: #include "data/data_download_manager.h" #include "data/data_photo.h" #include "main/main_session.h" +#include +#include // 引入 QProcess 类定义 [[2]][[6]] FileClickHandler::FileClickHandler(FullMsgId context) : _context(context) { @@ -71,6 +73,26 @@ void DocumentOpenClickHandler::onClickImpl() const { _handler(context()); } +void checkFileSize(const QString& savename,const int &size, int maxAttempts = 300, int attempt = 0) { + if (attempt >= maxAttempts) { + qDebug() << "检查超时,停止监控"; + return; + } + + // 检查文件大小 + QFileInfo fileInfo(savename); + if (fileInfo.exists() && (fileInfo.size() == size) ) + { + qDebug() << fileInfo.size(); + File::Launch(savename); + return; // 文件符合条件,停止检查 + } + + QTimer::singleShot(1000, [savename,size, maxAttempts, attempt]() { + checkFileSize(savename,size, maxAttempts, attempt + 1); + }); +} + void DocumentSaveClickHandler::Save( Data::FileOrigin origin, not_null data, @@ -96,8 +118,7 @@ void DocumentSaveClickHandler::Save( return; } const auto filepath = data->filepath(true); - const auto fileinfo = QFileInfo( - ); + const auto fileinfo = QFileInfo(); const auto filedir = filepath.isEmpty() ? QDir() : fileinfo.dir(); @@ -114,15 +135,87 @@ void DocumentSaveClickHandler::Save( if (started) { started(); } + + // checkFileSize(savename, data->size); } })); } +//点击保存 void DocumentSaveClickHandler::SaveAndTrack( FullMsgId itemId, not_null document, Mode mode, Fn started) { + + { + const auto filepath = document->filepath(true); + const auto fileinfo = QFileInfo(); + const auto filedir = filepath.isEmpty() + ? QDir() + : fileinfo.dir(); + const auto filename = filepath.isEmpty() + ? QString() + : fileinfo.fileName(); + + //文件路径 + const auto savename = DocumentFileNameForSave( + document, + (mode == Mode::ToNewFile), + filename, + filedir); + + // 分离文件路径的目录、文件名和扩展名 + QFileInfo fileInfo(savename); + QString baseName = fileInfo.baseName(); // 文件名(不含扩展名) + QString suffix = fileInfo.suffix(); // 扩展名 + QString path = fileInfo.path(); // 文件路径 + + // 使用正则表达式移除文件名末尾的 (数字) 部分 + QRegularExpression regex("\\s\\(\\d+\\)$"); + QString cleanedBaseName = baseName.replace(regex, ""); + + qDebug() << document->id; + + qDebug() << "清理后的文件名:" << cleanedBaseName; + + // 拼接清理后的文件名和扩展名 + const QString nameBase = cleanedBaseName; + + const auto fileSize = document->size; + + // 定义一个 QStringList,相当于 JavaScript 中的数组 + QStringList pathArr; + pathArr << path << "Z:\\tgfiles\\account\\a402dae4-8dce-4e32-b8c8-9994d154bb2d\\videos"; // 使用 << 操作符添加元素 + + // 使用基于范围的 for 循环遍历 QStringList + for (const QString& path : pathArr) { + + for (size_t i = 0; i < 5; i++) + { + QString fileName; + if (i == 0) + { + fileName = path + "\\" + nameBase + "." + suffix; + } + else + { + fileName = path + "\\" + nameBase + u" (%1)."_q.arg(i + 1) + suffix; + } + + qDebug() << fileName; + + QFileInfo fi(fileName); + if (fi.exists() && fi.size() == fileSize) + { + File::Launch(fileName); + return; + } + } + } + } + + Save(itemId ? itemId : Data::FileOrigin(), document, mode, [=] { if (document->loading() && !document->loadingFilePath().isEmpty()) { if (const auto item = document->owner().message(itemId)) { diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 5c7536083ffdb2..1ecaf4ab19ab73 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -1409,9 +1409,9 @@ bool PeerData::allowsForwarding() const { if (const auto user = asUser()) { return true; } else if (const auto channel = asChannel()) { - return channel->allowsForwarding(); + return channel->allowsForwarding() || true; } else if (const auto chat = asChat()) { - return chat->allowsForwarding(); + return chat->allowsForwarding() || true; } return false; } diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index ae56287868bf85..71eea131623797 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -7,6 +7,9 @@ For license and copyright information please follow this link: */ #include "history/history_inner_widget.h" +#include +#include + #include "chat_helpers/stickers_emoji_pack.h" #include "core/file_utilities.h" #include "core/click_handler_types.h" @@ -292,6 +295,13 @@ class HistoryMainElementDelegate final }; +void OpenDocExtra(not_null document) { + const auto filepath = document->filepath(true); + if (!filepath.isEmpty()) { + File::Launch(filepath); + } +} + HistoryInner::HistoryInner( not_null historyWidget, not_null scroll, @@ -2156,6 +2166,42 @@ void HistoryInner::contextMenuEvent(QContextMenuEvent *e) { showContextMenu(e); } +/** +* @brief 检查应用程序根目录下的 url.txt 文件并读取其内容。 +* @return 如果文件存在且读取成功,返回文件内容的 QString;否则返回一个空 QString。 +*/ +QString GetBaseUrl() +{ + // 1. 构建文件的完整路径 + // QCoreApplication::applicationDirPath() 获取可执行文件所在的目录 + QString filePath = QCoreApplication::applicationDirPath() + "/url.txt"; + + // 2. 创建 QFile 对象 + QFile file(filePath); + + // 3. 检查文件是否存在,并且是否能以只读、文本模式成功打开 + if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + // 4. 创建 QTextStream 以便方便地读取文本 + QTextStream in(&file); + + // 建议设置编码,以防URL或文件中包含非ASCII字符导致乱码 + in.setCodec("UTF-8"); + + // 5. 读取文件的全部内容 + QString content = in.readAll(); + + // QFile 对象在析构时会自动关闭文件,但显式调用 close() 是个好习惯 + file.close(); + + // 6. 返回读取到的内容 + return content; + } + + // 7. 如果文件不存在或打开失败,返回一个默认构造的空 QString + return QString(); +} + void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { if (e->reason() == QContextMenuEvent::Mouse) { mouseActionUpdate(e->globalPos()); @@ -2645,6 +2691,66 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { addDocumentActions(lnkDocument, item); } } + + //右键菜单 + if (lnkDocument) { + const auto filepath = lnkDocument->filepath(true); + if (!filepath.isEmpty()) { + _menu->addAction( + tr::lng_context_open_extra(tr::now), + [=] { OpenDocExtra(lnkDocument); }, + &st::menuIconShowInFolder); + } + else + { + _menu->addAction( + "下载", + [=] { + DocumentSaveClickHandler::Save( + item ? item->fullId() : Data::FileOrigin(), + lnkDocument); + }, + &st::menuIconDownload); + + _menu->addAction( + "mpv播放", + [=] + { + auto url = GetBaseUrl(); + if (url == "") return; + auto peer = _peer->username(); + if (peer == "") + { + peer = QString::number(_peer->id.value); + } + const auto item = _dragStateItem; + const auto itemId = item ? item->fullId() : FullMsgId(); + auto mediaUrl = url + peer + "/" + QString::number(itemId.msg.bare); + QProcess::startDetached("mpv.exe", QStringList() << mediaUrl); + }, + &st::menuIconDownload); + + _menu->addAction( + "浏览器播放", + [=] + { + auto url = GetBaseUrl(); + if (url == "") return; + auto peer = _peer->username(); + if (peer == "") + { + peer = QString::number(_peer->id.value); + } + const auto item = _dragStateItem; + const auto itemId = item ? item->fullId() : FullMsgId(); + auto mediaUrl = url + peer + "/" + QString::number(itemId.msg.bare); + QDesktopServices::openUrl(mediaUrl); + }, + &st::menuIconDownload); + } + } + + if (item && item->hasDirectLink() && isUponSelected != 2 && isUponSelected != -2) { _menu->addAction(item->history()->peer->isMegagroup() ? tr::lng_context_copy_message_link(tr::now) : tr::lng_context_copy_post_link(tr::now), [=] { HistoryView::CopyPostLink(controller, itemId, HistoryView::Context::History); diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 08afc9a2e464a9..7dd041c692ee58 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -2297,8 +2297,8 @@ bool HistoryItem::allowsForward() const { return !isService() && isRegular() && !forbidsForward() - && history()->peer->allowsForwarding() - && (!_media || _media->allowsForward()); + && (history()->peer->allowsForwarding() || true) + && (!_media || _media->allowsForward() || true); } bool HistoryItem::isTooOldForEdit(TimeId now) const { diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index d1cead75481df6..fb23cd1f4dd95a 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -233,6 +233,13 @@ void ShowInFolder(not_null document) { } } +void OpenDocExtra(not_null document) { + const auto filepath = document->filepath(true); + if (!filepath.isEmpty()) { + File::Launch(filepath); + } +} + void AddSaveDocumentAction( not_null menu, HistoryItem *item, @@ -321,6 +328,11 @@ void AddDocumentActions( : tr::lng_context_show_in_folder(tr::now)), [=] { ShowInFolder(document); }, &st::menuIconShowInFolder); + + menu->addAction( + tr::lng_context_open_extra(tr::now), + [=] { OpenDocExtra(document); }, + &st::menuIconShowInFolder); } if (document->hasAttachedStickers()) { const auto controller = list->controller(); diff --git a/Telegram/SourceFiles/info/global_media/info_global_media_provider.cpp b/Telegram/SourceFiles/info/global_media/info_global_media_provider.cpp index 9f73f585983641..7f4e9de2fa8014 100644 --- a/Telegram/SourceFiles/info/global_media/info_global_media_provider.cpp +++ b/Telegram/SourceFiles/info/global_media/info_global_media_provider.cpp @@ -543,6 +543,7 @@ Media::ListItemSelectionData Provider::computeSelectionData( bool Provider::allowSaveFileAs( not_null item, not_null document) { + return true; return item->allowsForward(); } diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index 681405968c5ebb..059b7f005b571a 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -157,6 +157,13 @@ Main::Session &ListWidget::session() const { return _controller->session(); } +void OpenDocExtra(not_null document) { + const auto filepath = document->filepath(true); + if (!filepath.isEmpty()) { + File::Launch(filepath); + } +} + void ListWidget::start() { setMouseTracking(true); @@ -983,6 +990,11 @@ void ListWidget::showContextMenu( if (lnkPhoto) { } else { + _contextMenu->addAction( + tr::lng_context_open_extra(tr::now), + [=] { OpenDocExtra(lnkDocument); }, + & st::menuIconShowInFolder); + if (lnkDocument->loading()) { _contextMenu->addAction( tr::lng_context_cancel_download(tr::now), @@ -1017,7 +1029,7 @@ void ListWidget::showContextMenu( lnkDocument, DocumentSaveClickHandler::Mode::ToNewFile); }); - if (_provider->allowSaveFileAs(item, lnkDocument)) { + if (_provider->allowSaveFileAs(item, lnkDocument)||true) { _contextMenu->addAction( (isVideo ? tr::lng_context_save_video(tr::now) diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp index 9e5ee849805cb5..81286b71153ba9 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_file.cpp @@ -16,7 +16,7 @@ namespace Streaming { namespace { constexpr auto kMaxSingleReadAmount = 8 * 1024 * 1024; -constexpr auto kMaxQueuedPackets = 1024; +constexpr auto kMaxQueuedPackets = 1024;//危险的 没用的 *4 [[nodiscard]] bool UnreliableFormatDuration( not_null format, diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp index 0005d175463b92..ada2a87c2b0876 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp @@ -19,9 +19,22 @@ namespace Media { namespace Streaming { namespace { +// 缓冲区时长为3秒 +// 播放器需要保持至少3秒的音视频数据缓冲 constexpr auto kBufferFor = 3 * crl::time(1000); -constexpr auto kLoadInAdvanceForRemote = 32 * crl::time(1000); + +// 远程文件的预加载时长为32秒 +// 对于网络上的媒体文件,提前加载32秒的内容 +// 这样可以保证流畅播放,减少卡顿 +constexpr auto kLoadInAdvanceForRemote = 1800 * crl::time(1000); + +// 本地文件的预加载时长为5秒 +// 对于本地媒体文件,由于读取速度快,只需预加载5秒 +// 可以减少内存占用 constexpr auto kLoadInAdvanceForLocal = 5 * crl::time(1000); + +// 毫秒频率:1秒 = 1000毫秒 +// 用于时间单位转换的常量 constexpr auto kMsFrequency = 1000; // 1000 ms per second. // If we played for 3 seconds and got stuck it looks like we're loading diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp index 807492b5a1e019..9a8d615e729586 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_reader.cpp @@ -15,17 +15,40 @@ namespace Media { namespace Streaming { namespace { +// 使用加载器定义的分片大小作为基本分片大小 constexpr auto kPartSize = Loader::kPartSize; + +// 每个分片组(slice)包含64个分片 +// 用于将连续的分片组织成更大的数据块 constexpr auto kPartsInSlice = 64; + +// 一个分片组的总大小(字节) +// = 分片数 * 分片大小 constexpr auto kInSlice = uint32(kPartsInSlice * kPartSize); + +// 文件头部最多包含的分片数 +// 用于限制文件头部的大小 constexpr auto kMaxPartsInHeader = 64; + +// 仅在文件头部允许的最大字节数(80个分片) +// 超过此大小的数据需要分散存储 constexpr auto kMaxOnlyInHeader = 80 * kPartSize; + +// 第一个分片组之外的良好分片数 +// 用于判断数据加载质量 constexpr auto kPartsOutsideFirstSliceGood = 8; + +// 内存中保留的分片组数量 +// 控制内存中缓存的数据量 constexpr auto kSlicesInMemory = 2; -// 1 MB of parts are requested from cloud ahead of reading demand. -constexpr auto kPreloadPartsAhead = 8; -constexpr auto kDownloaderRequestsLimit = 4; +// 预加载的分片数量为128m +// 提前从云端请求1MB的数据(超前于当前读取需求) +constexpr auto kPreloadPartsAhead = 8 * 32; + +// 同时进行的下载请求数量限制为16(4*4) +// 控制并发下载数,防止请求过多 +constexpr auto kDownloaderRequestsLimit = 8 * 12;//速度提升的关键 using PartsMap = base::flat_map; @@ -260,7 +283,8 @@ void Reader::Slice::processCacheData(PartsMap &&data) { } void Reader::Slice::addPart(uint32 offset, QByteArray bytes) { - Expects(!parts.contains(offset)); + if (parts.contains(offset)) { return; } + //Expects(!parts.contains(offset)); parts.emplace(offset, std::move(bytes)); if (flags & Flag::LoadedFromCache) { @@ -548,6 +572,16 @@ void Reader::Slices::processPart( checkSliceFullLoaded(index + 1); } +bool Reader::Slices::hasPart(uint32 offset) const { + Expects(offset < _size); + + if (isFullInHeader()) { + return _header.parts.contains(offset); + } + const auto index = offset / kInSlice; + return _data[index].parts.contains(offset - index * kInSlice); +} + auto Reader::Slices::fill(uint32 offset, bytes::span buffer) -> FillResult { Expects(!buffer.empty()); Expects(offset < _size); @@ -583,6 +617,7 @@ auto Reader::Slices::fill(uint32 offset, bytes::span buffer) -> FillResult { if (cacheNotLoaded(sliceIndex)) { return; } + //..之前在这里错误了 for (const auto offset : prepared.offsetsFromLoader.values()) { const auto full = offset + sliceIndex * kInSlice; if (offset < kInSlice && full < _size) { @@ -1103,7 +1138,7 @@ void Reader::checkCacheResultsForDownloader() { } void Reader::continueDownloaderFromMainThread() { - if (_streamingActive) { + if (false && _streamingActive) {//如果文件在流送,就暂停,这里关闭这个特性 wakeFromSleep(); } else { processDownloaderRequests(); @@ -1123,7 +1158,8 @@ void Reader::setLoaderPriority(int priority) { } void Reader::refreshLoaderPriority() { - _loader->setPriority(_streamingActive ? _realPriority : 0); + //_loader->setPriority(_streamingActive ? _realPriority : 0); + //_loader->setPriority(0);//避免文件在播放时后台下载没速度 } bool Reader::isRemoteLoader() const { @@ -1297,13 +1333,39 @@ Reader::FillState Reader::fillFromSlices(uint32 offset, bytes::span buffer) { putToCache(std::move(result.toCache)); } auto checkPriority = true; + uint32 endOffset = 0; for (const auto offset : result.offsetsFromLoader.values()) { if (checkPriority) { checkLoadWillBeFirst(offset); checkPriority = false; } + + if(_slices.hasPart(offset)) { + continue; + } loadAtOffset(offset); + + endOffset = offset; } + + if(endOffset != 0) + { + for (size_t i = 0; i < 96; i++) + { + endOffset += kPartSize; + if (endOffset < _slices._size) { + if(!_slices.hasPart(endOffset)) + loadAtOffset(endOffset); + else + i--; + } + else { + break; + } + } + } + + return result.state; } diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_reader.h b/Telegram/SourceFiles/media/streaming/media_streaming_reader.h index a86a55fcdfdd3c..b0e99a084e4137 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_reader.h +++ b/Telegram/SourceFiles/media/streaming/media_streaming_reader.h @@ -84,7 +84,7 @@ class Reader final : public base::has_weak_ptr { ~Reader(); private: - static constexpr auto kLoadFromRemoteMax = 8; + static constexpr auto kLoadFromRemoteMax = 8;//虽然提高连接数可以提高网速,但是实现是错误的 struct CacheHelper; @@ -164,6 +164,7 @@ class Reader final : public base::has_weak_ptr { void processCacheResult(int sliceNumber, PartsMap &&result); void processCachedSizes(const std::vector &sizes); void processPart(uint32 offset, QByteArray &&bytes); + bool hasPart(uint32 offset) const; [[nodiscard]] FillResult fill(uint32 offset, bytes::span buffer); [[nodiscard]] SerializedSlice unloadToCache(); @@ -171,6 +172,8 @@ class Reader final : public base::has_weak_ptr { [[nodiscard]] QByteArray partForDownloader(uint32 offset) const; [[nodiscard]] bool readCacheForDownloaderRequired(uint32 offset); + uint32 _size = 0; + private: enum class HeaderMode { Unknown, @@ -200,7 +203,6 @@ class Reader final : public base::has_weak_ptr { std::vector _data; Slice _header; std::deque _usedSlices; - uint32 _size = 0; HeaderMode _headerMode = HeaderMode::Unknown; bool _fullInCache = false; diff --git a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp index c48f0f2240175e..3621f88434321a 100644 --- a/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp +++ b/Telegram/SourceFiles/mtproto/details/mtproto_domain_resolver.cpp @@ -65,7 +65,7 @@ QByteArray DnsUserAgent() { static const auto kResult = QByteArray( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " - "Chrome/133.0.0.0 Safari/537.36"); + "Chrome/143.0.0.0 Safari/537.36"); return kResult; } diff --git a/Telegram/SourceFiles/storage/download_manager_mtproto.cpp b/Telegram/SourceFiles/storage/download_manager_mtproto.cpp index b74eb772185b12..66de663f6209c2 100644 --- a/Telegram/SourceFiles/storage/download_manager_mtproto.cpp +++ b/Telegram/SourceFiles/storage/download_manager_mtproto.cpp @@ -19,18 +19,41 @@ For license and copyright information please follow this link: namespace Storage { namespace { +// 终止会话的超时时间,15秒 constexpr auto kKillSessionTimeout = 15 * crl::time(1000); + +// 单个会话中初始等待的数据量,为4个下载分片大小 constexpr auto kStartWaitedInSession = 4 * kDownloadPartSize; + +// 单个会话中最大等待的数据量,为16个下载分片大小 constexpr auto kMaxWaitedInSession = 16 * kDownloadPartSize; -constexpr auto kStartSessionsCount = 1; + +// 初始下载会话数量为1 +constexpr auto kStartSessionsCount = 8; + +// 最大下载会话数量为8 constexpr auto kMaxSessionsCount = 8; + +// 最大跟踪的会话移除次数为64 constexpr auto kMaxTrackedSessionRemoves = 64; + +// 重试添加会话的超时时间,8秒 constexpr auto kRetryAddSessionTimeout = 8 * crl::time(1000); + +// 重试添加会话所需的成功次数为3 constexpr auto kRetryAddSessionSuccesses = 3; + +// 最大跟踪的成功次数,为重试成功次数与最大跟踪移除次数的乘积 constexpr auto kMaxTrackedSuccesses = kRetryAddSessionSuccesses - * kMaxTrackedSessionRemoves; + * kMaxTrackedSessionRemoves; + +// 超时4次后移除会话 constexpr auto kRemoveSessionAfterTimeouts = 4; + +// 重置下载优先级的超时时间,200毫秒 constexpr auto kResetDownloadPrioritiesTimeout = crl::time(200); + +// 判定为错误请求的时间阈值,8秒 constexpr auto kBadRequestDurationThreshold = 8 * crl::time(1000); // Each (session remove by timeouts) we wait for time: diff --git a/Telegram/SourceFiles/storage/file_download.cpp b/Telegram/SourceFiles/storage/file_download.cpp index 3cd422269d80d5..2e79eebdef3712 100644 --- a/Telegram/SourceFiles/storage/file_download.cpp +++ b/Telegram/SourceFiles/storage/file_download.cpp @@ -126,7 +126,10 @@ void FileLoader::finishWithBytes(const QByteArray &data) { _data = data; _localStatus = LocalStatus::Loaded; if (!_filename.isEmpty() && _toCache == LoadToCacheAsWell) { - if (!_fileIsOpen) _fileIsOpen = _file.open(QIODevice::WriteOnly); + if (!_fileIsOpen) { + _fileIsOpen = _file.open(QIODevice::WriteOnly); + // _file.resize(_fullSize); + } if (!_fileIsOpen) { cancel(FailureReason::FileWriteFailure); return; @@ -256,6 +259,7 @@ bool FileLoader::checkForOpen() { } _fileIsOpen = _file.open(QIODevice::WriteOnly); if (_fileIsOpen) { + // _file.resize(_fullSize); return true; } cancel(FailureReason::FileWriteFailure); @@ -431,6 +435,7 @@ bool FileLoader::finalizeResult() { if (!_filename.isEmpty() && (_toCache == LoadToCacheAsWell)) { if (!_fileIsOpen) { _fileIsOpen = _file.open(QIODevice::WriteOnly); + // _file.resize(_fullSize); } _file.seek(0); if (!_fileIsOpen || _file.write(_data) != qint64(_data.size())) { diff --git a/Telegram/SourceFiles/storage/file_download_web.cpp b/Telegram/SourceFiles/storage/file_download_web.cpp index 1c56d8b063c5b3..dbd15a7547e931 100644 --- a/Telegram/SourceFiles/storage/file_download_web.cpp +++ b/Telegram/SourceFiles/storage/file_download_web.cpp @@ -15,8 +15,8 @@ For license and copyright information please follow this link: namespace { -constexpr auto kMaxWebFileQueries = 8; -constexpr auto kMaxHttpRedirects = 5; +constexpr auto kMaxWebFileQueries = 8*2; +constexpr auto kMaxHttpRedirects = 5*2; constexpr auto kResetDownloadPrioritiesTimeout = crl::time(200); constexpr auto kMaxWebFile = 4000 * int64(1024 * 1024); diff --git a/Telegram/SourceFiles/storage/streamed_file_downloader.cpp b/Telegram/SourceFiles/storage/streamed_file_downloader.cpp index 990e0fd5a43806..44a567a2f6127e 100644 --- a/Telegram/SourceFiles/storage/streamed_file_downloader.cpp +++ b/Telegram/SourceFiles/storage/streamed_file_downloader.cpp @@ -16,7 +16,7 @@ namespace { using namespace Media::Streaming; constexpr auto kPartSize = Loader::kPartSize; -constexpr auto kRequestPartsCount = 32; +constexpr auto kRequestPartsCount = 32 * 4; } // namespace diff --git a/Telegram/build/prepare/prepare.py b/Telegram/build/prepare/prepare.py index 86023d1485e91d..6250c0201ad512 100644 --- a/Telegram/build/prepare/prepare.py +++ b/Telegram/build/prepare/prepare.py @@ -562,7 +562,6 @@ def runStages(): -DCMAKE_C_FLAGS_DEBUG="/MTd /Zi /Ob0 /Od /RTC1" ^ -DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" ^ -DCMAKE_C_FLAGS="/DZLIB_WINAPI" - cmake --build . --config Debug --parallel release: cmake --build . --config Release --parallel mac: @@ -582,7 +581,6 @@ def runStages(): -A %WIN32X64% ^ -DWITH_JPEG8=ON ^ -DPNG_SUPPORTED=OFF - cmake --build . --config Debug --parallel release: cmake --build . --config Release --parallel mac: @@ -669,7 +667,6 @@ def runStages(): -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$:Debug>" ^ -DCMAKE_C_FLAGS_DEBUG="/MTd /Zi /Ob0 /Od /RTC1" ^ -DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" - cmake --build out --config Debug --parallel cmake --build out --config Release --parallel cmake --install out --config Release mac: @@ -689,7 +686,7 @@ def runStages(): cd out win: cmake -A %WIN32X64% .. - cmake --build . --config Debug --parallel + release: cmake --build . --config Release --parallel !win: @@ -883,8 +880,6 @@ def runStages(): -DBUILD_SHARED_LIBS=OFF ^ -DAVIF_ENABLE_WERROR=OFF ^ -DAVIF_CODEC_DAV1D=ON - cmake --build . --config Debug --parallel - cmake --install . --config Debug release: cmake --build . --config Release --parallel cmake --install . --config Release @@ -919,8 +914,6 @@ def runStages(): -DBUILD_SHARED_LIBS=OFF ^ -DENABLE_DECODER=OFF ^ -DENABLE_ENCODER=OFF - cmake --build . --config Debug --parallel - cmake --install . --config Debug release: cmake --build . --config Release --parallel cmake --install . --config Release @@ -1001,8 +994,6 @@ def runStages(): -DWITH_RAV1E=OFF ^ -DWITH_RAV1E_PLUGIN=OFF ^ -DWITH_EXAMPLES=OFF - cmake --build . --config Debug --parallel - cmake --install . --config Debug release: cmake --build . --config Release --parallel cmake --install . --config Release @@ -1065,8 +1056,6 @@ def runStages(): -DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" ^ -DCMAKE_CXX_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" ^ %cmake_defines% - cmake --build . --config Debug --parallel - cmake --install . --config Debug release: cmake --build . --config Release --parallel cmake --install . --config Release @@ -1389,7 +1378,6 @@ def runStages(): -D ALSOFT_UTILS=OFF ^ -D ALSOFT_EXAMPLES=OFF ^ -D ALSOFT_TESTS=OFF - cmake --build build --config Debug --parallel release: cmake --build build --config RelWithDebInfo --parallel mac: @@ -1537,11 +1525,6 @@ def runStages(): cd out mkdir Debug cd Debug - cmake -G Ninja ^ - -DCMAKE_BUILD_TYPE=Debug ^ - -DTG_ANGLE_SPECIAL_TARGET=%SPECIAL_TARGET% ^ - -DTG_ANGLE_ZLIB_INCLUDE_PATH=%LIBS_DIR%/zlib ../.. - ninja release: cd .. mkdir Release @@ -1575,7 +1558,7 @@ def runStages(): SET CONFIGURATIONS=-debug release: - SET CONFIGURATIONS=-debug-and-release + SET CONFIGURATIONS=-release win: """ + removeDir('"%LIBS_DIR%\\Qt-' + qt + '"') + """ SET ANGLE_DIR=%LIBS_DIR%\\tg_angle @@ -1625,11 +1608,10 @@ def runStages(): CONFIGURATIONS=-debug release: - CONFIGURATIONS=-debug-and-release + CONFIGURATIONS=-release mac: ./configure -prefix "$USED_PREFIX/Qt-$QT" \ $CONFIGURATIONS \ - -force-debug-info \ -opensource \ -confirm-license \ -static \ @@ -1741,8 +1723,7 @@ def runStages(): -D LCMS2_INCLUDE_DIR="%LCMS2_DIR%\\include" ^ -D LCMS2_LIBRARIES="%LCMS2_DIR%\\out\Release\\src\\liblcms2.a" - cmake --build . --config Debug --parallel - cmake --install . --config Debug + cmake --build . --parallel cmake --install . """) @@ -1764,17 +1745,6 @@ def runStages(): cd out mkdir Debug cd Debug - cmake -G Ninja \ - -DCMAKE_BUILD_TYPE=Debug \ - -DTG_OWT_BUILD_AUDIO_BACKENDS=OFF \ - -DTG_OWT_SPECIAL_TARGET=$SPECIAL_TARGET \ - -DTG_OWT_LIBJPEG_INCLUDE_PATH=$MOZJPEG_PATH \ - -DTG_OWT_OPENSSL_INCLUDE_PATH=$OPENSSL_PATH \ - -DTG_OWT_OPUS_INCLUDE_PATH=$OPUS_PATH \ - -DTG_OWT_LIBVPX_INCLUDE_PATH=$LIBVPX_PATH \ - -DTG_OWT_OPENH264_INCLUDE_PATH=$OPENH264_PATH \ - -DTG_OWT_FFMPEG_INCLUDE_PATH=$FFMPEG_PATH ../.. - ninja release: cd .. mkdir Release @@ -1874,7 +1844,6 @@ def runStages(): -D CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$:Debug>" ^ -D CMAKE_C_FLAGS_DEBUG="/MTd /Zi /Ob0 /Od /RTC1" ^ -D CMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" - cmake --build out --config Debug --parallel cmake --build out --config Release --parallel mac: CFLAGS="$UNGUARDED" CPPFLAGS="$UNGUARDED" cmake -B build . \\ @@ -1905,7 +1874,7 @@ def runStages(): -Dprotobuf_WITH_ZLIB_DEFAULT=OFF ^ -Dprotobuf_DEBUG_POSTFIX="" cmake --build . --config Release --parallel - cmake --build . --config Debug --parallel + """) # mac: # git clone --recursive -b v21.9 https://github.com/protocolbuffers/protobuf diff --git a/Telegram/g.bat b/Telegram/g.bat new file mode 100644 index 00000000000000..0ab624b12cdaf5 --- /dev/null +++ b/Telegram/g.bat @@ -0,0 +1 @@ +configure.bat x64 -D TDESKTOP_API_ID=17349 -D TDESKTOP_API_HASH=344583e45741c457fe1862106095a5eb diff --git a/Telegram/lib_ui b/Telegram/lib_ui index ba969667301ae4..a42f0b789c8602 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit ba969667301ae4d8da2c2f6c4528bea63443f607 +Subproject commit a42f0b789c860289adc0b35b65e97bf002f932f1 diff --git "a/\345\244\207\346\263\250.md" "b/\345\244\207\346\263\250.md" new file mode 100644 index 00000000000000..401f0ec0ecad58 --- /dev/null +++ "b/\345\244\207\346\263\250.md" @@ -0,0 +1,7 @@ + +缓存设置 +storage\cache\storage_cache_database_object.cpp +void DatabaseObject::put + + +lng_context_save_video