Allow video download from media viewer.

This commit is contained in:
John Preston 2019-03-14 16:03:02 +04:00
parent 2b7fb7a9a6
commit 5cae57601a
2 changed files with 141 additions and 123 deletions

View File

@ -282,24 +282,27 @@ void OverlayWidget::refreshLang() {
InvokeQueued(this, [this] { updateThemePreviewGeometry(); });
}
void OverlayWidget::moveToScreen() {
auto widgetScreen = [&](auto &&widget) -> QScreen* {
void OverlayWidget::moveToScreen(bool force) {
const auto widgetScreen = [&](auto &&widget) -> QScreen* {
if (auto handle = widget ? widget->windowHandle() : nullptr) {
return handle->screen();
}
return nullptr;
};
auto activeWindow = Core::App().getActiveWindow();
auto activeWindowScreen = widgetScreen(activeWindow);
auto myScreen = widgetScreen(this);
const auto activeWindow = Core::App().getActiveWindow();
const auto activeWindowScreen = widgetScreen(activeWindow);
const auto myScreen = widgetScreen(this);
if (activeWindowScreen && myScreen && myScreen != activeWindowScreen) {
windowHandle()->setScreen(activeWindowScreen);
}
const auto screen = activeWindowScreen ? activeWindowScreen : QApplication::primaryScreen();
const auto screen = activeWindowScreen
? activeWindowScreen
: QApplication::primaryScreen();
const auto available = screen->geometry();
if (geometry() != available) {
setGeometry(available);
if (!force && geometry() == available) {
return;
}
setGeometry(available);
auto navSkip = 2 * st::mediaviewControlMargin + st::mediaviewControlSize;
_closeNav = myrtlrect(width() - st::mediaviewControlMargin - st::mediaviewControlSize, st::mediaviewControlMargin, st::mediaviewControlSize, st::mediaviewControlSize);
@ -310,6 +313,10 @@ void OverlayWidget::moveToScreen() {
_rightNavIcon = centerrect(_rightNav, st::mediaviewRight);
_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (height() - _saveMsg.height()) / 2);
_photoRadialRect = QRect(QPoint((width() - st::radialSize.width()) / 2, (height() - st::radialSize.height()) / 2), st::radialSize);
resizeContentByScreenSize();
update();
}
bool OverlayWidget::videoShown() const {
@ -490,8 +497,7 @@ void OverlayWidget::updateControls() {
updateThemePreviewGeometry();
_saveVisible = (_photo && _photo->loaded())
|| (_doc && (_doc->loaded(DocumentData::FilePathResolve::Checked)
|| !documentContentShown()));
|| (_doc && _doc->filepath(DocumentData::FilePathResolve::Checked).isEmpty());
_saveNav = myrtlrect(width() - st::mediaviewIconSize.width() * 2, height() - st::mediaviewIconSize.height(), st::mediaviewIconSize.width(), st::mediaviewIconSize.height());
_saveNavIcon = centerrect(_saveNav, st::mediaviewSave);
_moreNav = myrtlrect(width() - st::mediaviewIconSize.width(), height() - st::mediaviewIconSize.height(), st::mediaviewIconSize.width(), st::mediaviewIconSize.height());
@ -720,6 +726,10 @@ QRect OverlayWidget::contentRect() const {
void OverlayWidget::contentSizeChanged() {
_width = _w;
_height = _h;
resizeContentByScreenSize();
}
void OverlayWidget::resizeContentByScreenSize() {
if (_w > 0 && _h > 0) {
_zoomToScreen = float64(width()) / _w;
if (_h * _zoomToScreen > height()) {
@ -742,9 +752,10 @@ void OverlayWidget::contentSizeChanged() {
_w = qRound(_w / (-_zoomToScreen + 1));
_h = qRound(_h / (-_zoomToScreen + 1));
}
snapXY();
} else {
_zoom = 0;
_w = _width;
_h = _height;
}
_x = (width() - _w) / 2;
_y = (height() - _h) / 2;
@ -808,19 +819,18 @@ void OverlayWidget::step_radial(crl::time ms, bool timer) {
update(radialRect());
}
const auto ready = _doc && _doc->loaded();
const auto streamVideo = ready && (_doc->isAnimation() || _doc->isVideoFile());
const auto streamVideo = ready && _doc->canBePlayed();
const auto tryOpenImage = ready && (_doc->size < App::kImageSizeLimit);
if (ready && ((tryOpenImage && !_radial.animating()) || streamVideo)) {
_streamingStartPaused = false;
if (!_doc->data().isEmpty() && streamVideo) {
displayDocument(_doc, App::histItemById(_msgid));
_streamingStartPaused = true;
if (streamVideo) {
redisplayContent();
} else {
auto &location = _doc->location(true);
if (location.accessEnable()) {
if (streamVideo
|| _doc->isTheme()
if (_doc->isTheme()
|| QImageReader(location.name()).canRead()) {
displayDocument(_doc, App::histItemById(_msgid));
redisplayContent();
}
location.accessDisable();
}
@ -996,25 +1006,19 @@ void OverlayWidget::dropdownHidden() {
}
void OverlayWidget::onScreenResized(int screen) {
if (isHidden()) return;
bool ignore = false;
auto screens = QApplication::screens();
if (screen >= 0 && screen < screens.size()) {
if (auto screenHandle = windowHandle()->screen()) {
if (screens.at(screen) != screenHandle) {
ignore = true;
}
}
if (isHidden()) {
return;
}
if (!ignore) {
const auto screens = QApplication::screens();
const auto changed = (screen >= 0 && screen < screens.size())
? screens[screen]
: nullptr;
if (!windowHandle()
|| !windowHandle()->screen()
|| !changed
|| windowHandle()->screen() == changed) {
moveToScreen();
const auto item = App::histItemById(_msgid);
if (_photo) {
displayPhoto(_photo, item);
} else if (_doc) {
displayDocument(_doc, item);
}
}
}
@ -1062,16 +1066,11 @@ void OverlayWidget::onSaveAs() {
if (_doc->data().isEmpty()) location.accessDisable();
} else {
if (!documentContentShown()) {
DocumentSaveClickHandler::Save(
fileOrigin(),
_doc,
DocumentSaveClickHandler::Mode::ToNewFile);
updateControls();
} else {
_saveVisible = false;
update(_saveNav);
}
DocumentSaveClickHandler::Save(
fileOrigin(),
_doc,
DocumentSaveClickHandler::Mode::ToNewFile);
updateControls();
updateOver(_lastMouseMovePos);
}
} else {
@ -1136,7 +1135,7 @@ void OverlayWidget::onDownload() {
}
QString toName;
if (_doc) {
const FileLocation &location(_doc->location(true));
const auto &location = _doc->location(true);
if (location.accessEnable()) {
if (!QDir().exists(path)) QDir().mkpath(path);
toName = filedialogNextFilename(
@ -1151,7 +1150,7 @@ void OverlayWidget::onDownload() {
}
location.accessDisable();
} else {
if (!documentContentShown()) {
if (_doc->filepath(DocumentData::FilePathResolve::Checked).isEmpty()) {
DocumentSaveClickHandler::Save(
fileOrigin(),
_doc,
@ -1186,6 +1185,9 @@ void OverlayWidget::onDownload() {
void OverlayWidget::onSaveCancel() {
if (_doc && _doc->loading()) {
_doc->cancel();
if (_doc->canBePlayed()) {
redisplayContent();
}
}
}
@ -1450,7 +1452,7 @@ std::optional<OverlayWidget::CollageKey> OverlayWidget::collageKey() const {
if (const auto item = App::histItemById(_msgid)) {
if (const auto media = item->media()) {
if (const auto page = media->webpage()) {
for (const auto item : page->collage.items) {
for (const auto &item : page->collage.items) {
if (item == _photo || item == _doc) {
return item;
}
@ -1695,6 +1697,10 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
displayDocument(nullptr, item);
return;
}
if (isHidden()) {
moveToScreen();
}
clearStreaming();
destroyThemePreview();
_doc = nullptr;
@ -1703,13 +1709,9 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
_radial.stop();
refreshMediaViewer();
_photoRadialRect = QRect(QPoint((width() - st::radialSize.width()) / 2, (height() - st::radialSize.height()) / 2), st::radialSize);
_zoom = 0;
refreshCaption(item);
_zoom = 0;
_zoomToScreen = 0;
Auth().downloader().clearPriorities();
_blurred = true;
@ -1717,9 +1719,6 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
_down = OverNone;
_w = ConvertScale(photo->width());
_h = ConvertScale(photo->height());
if (isHidden()) {
moveToScreen();
}
contentSizeChanged();
if (_msgid && item) {
_from = item->senderOriginal();
@ -1738,30 +1737,33 @@ void OverlayWidget::destroyThemePreview() {
_themeCancel.destroy();
}
void OverlayWidget::redisplayContent() {
if (isHidden()) {
return;
}
const auto item = App::histItemById(_msgid);
if (_photo) {
displayPhoto(_photo, item);
} else {
displayDocument(_doc, item);
}
}
// Empty messages shown as docs: doc can be nullptr.
void OverlayWidget::displayDocument(DocumentData *doc, HistoryItem *item) {
const auto documentChanged = !doc
|| (doc != _doc)
|| (item && item->fullId() != _msgid);
if (documentChanged
|| (!doc->isAnimation() && !doc->isVideoFile())
|| !doc->canBePlayed()) {
_fullScreenVideo = false;
_current = QPixmap();
clearStreaming();
} else if (videoShown()) {
_current = QPixmap();
}
if (documentChanged || !doc->isTheme()) {
destroyThemePreview();
if (isHidden()) {
moveToScreen();
}
_fullScreenVideo = false;
_current = QPixmap();
clearStreaming();
destroyThemePreview();
_doc = doc;
_photo = nullptr;
_radial.stop();
refreshMediaViewer();
if (documentChanged) {
if ((item ? item->fullId() : FullMsgId()) != _msgid) {
refreshCaption(item);
}
if (_doc) {
@ -1778,7 +1780,11 @@ void OverlayWidget::displayDocument(DocumentData *doc, HistoryItem *item) {
_doc->automaticLoad(fileOrigin(), item);
if (_doc->canBePlayed()) {
initStreaming();
if (_doc->loading()) {
initStreamingThumbnail();
} else {
initStreaming();
}
} else if (_doc->isTheme()) {
initThemePreview();
} else {
@ -1857,9 +1863,6 @@ void OverlayWidget::displayDocument(DocumentData *doc, HistoryItem *item) {
_w = contentSize.width();
_h = contentSize.height();
}
if (isHidden()) {
moveToScreen();
}
contentSizeChanged();
if (_msgid && item) {
_from = item->senderOriginal();
@ -2085,8 +2088,7 @@ void OverlayWidget::handleStreamingError(Streaming::Error &&error) {
_doc->setInappPlaybackFailed();
}
if (!_doc->canBePlayed()) {
clearStreaming();
displayDocument(_doc, App::histItemById(_msgid));
redisplayContent();
} else {
_streamed->lastError = std::move(error);
playbackWaitingChange(false);
@ -2134,51 +2136,52 @@ void OverlayWidget::initThemePreview() {
Assert(_doc && _doc->isTheme());
auto &location = _doc->location();
if (!location.isEmpty() && location.accessEnable()) {
_themePreviewShown = true;
Window::Theme::CurrentData current;
current.backgroundId = Window::Theme::Background()->id();
current.backgroundImage = Window::Theme::Background()->createCurrentImage();
current.backgroundTiled = Window::Theme::Background()->tile();
const auto path = _doc->location().name();
const auto id = _themePreviewId = rand_value<uint64>();
const auto weak = make_weak(this);
crl::async([=, data = std::move(current)]() mutable {
auto preview = Window::Theme::GeneratePreview(
path,
std::move(data));
crl::on_main(weak, [=, result = std::move(preview)]() mutable {
if (id != _themePreviewId) {
return;
}
_themePreviewId = 0;
_themePreview = std::move(result);
if (_themePreview) {
_themeApply.create(
this,
langFactory(lng_theme_preview_apply),
st::themePreviewApplyButton);
_themeApply->show();
_themeApply->setClickedCallback([this] {
auto preview = std::move(_themePreview);
close();
Window::Theme::Apply(std::move(preview));
});
_themeCancel.create(
this,
langFactory(lng_cancel),
st::themePreviewCancelButton);
_themeCancel->show();
_themeCancel->setClickedCallback([this] { close(); });
updateControls();
}
update();
});
});
location.accessDisable();
if (location.isEmpty() || !location.accessEnable()) {
return;
}
_themePreviewShown = true;
Window::Theme::CurrentData current;
current.backgroundId = Window::Theme::Background()->id();
current.backgroundImage = Window::Theme::Background()->createCurrentImage();
current.backgroundTiled = Window::Theme::Background()->tile();
const auto path = _doc->location().name();
const auto id = _themePreviewId = rand_value<uint64>();
const auto weak = make_weak(this);
crl::async([=, data = std::move(current)]() mutable {
auto preview = Window::Theme::GeneratePreview(
path,
std::move(data));
crl::on_main(weak, [=, result = std::move(preview)]() mutable {
if (id != _themePreviewId) {
return;
}
_themePreviewId = 0;
_themePreview = std::move(result);
if (_themePreview) {
_themeApply.create(
this,
langFactory(lng_theme_preview_apply),
st::themePreviewApplyButton);
_themeApply->show();
_themeApply->setClickedCallback([this] {
auto preview = std::move(_themePreview);
close();
Window::Theme::Apply(std::move(preview));
});
_themeCancel.create(
this,
langFactory(lng_cancel),
st::themePreviewCancelButton);
_themeCancel->show();
_themeCancel->setClickedCallback([this] { close(); });
updateControls();
}
update();
});
});
location.accessDisable();
}
void OverlayWidget::refreshClipControllerGeometry() {
@ -2393,7 +2396,19 @@ void OverlayWidget::validatePhotoCurrentImage() {
}
}
void OverlayWidget::checkLoadingWhileStreaming() {
if (_streamed && _doc->loading()) {
crl::on_main(this, [=, doc = _doc] {
if (!isHidden() && _doc == doc) {
redisplayContent();
}
});
}
}
void OverlayWidget::paintEvent(QPaintEvent *e) {
checkLoadingWhileStreaming();
const auto r = e->rect();
const auto &region = e->region();
const auto rects = region.rects();

View File

@ -174,7 +174,7 @@ private:
void playbackWaitingChange(bool waiting);
void updateOver(QPoint mpos);
void moveToScreen();
void moveToScreen(bool force = false);
bool moveToNext(int delta);
void preloadData(int delta);
@ -227,10 +227,13 @@ private:
void updateControls();
void updateActions();
void resizeCenteredControls();
void resizeContentByScreenSize();
void checkLoadingWhileStreaming();
void displayPhoto(not_null<PhotoData*> photo, HistoryItem *item);
void displayDocument(DocumentData *document, HistoryItem *item);
void displayFinished();
void redisplayContent();
void findCurrent();
void updateCursor();