mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Fix captions selection in column albums.
This commit is contained in:
parent
6d9c529a65
commit
6e682643df
11 changed files with 119 additions and 50 deletions
|
@ -108,12 +108,38 @@ TextForMimeData HistoryItemText(not_null<HistoryItem*> item) {
|
||||||
TextForMimeData HistoryGroupText(not_null<const Data::Group*> group) {
|
TextForMimeData HistoryGroupText(not_null<const Data::Group*> group) {
|
||||||
Expects(!group->items.empty());
|
Expects(!group->items.empty());
|
||||||
|
|
||||||
|
const auto columnAlbum = [&] {
|
||||||
|
const auto item = group->items.front();
|
||||||
|
if (const auto media = item->media()) {
|
||||||
|
if (const auto document = media->document()) {
|
||||||
|
return !document->isVideoFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}();
|
||||||
|
const auto hasCaption = [](not_null<HistoryItem*> item) {
|
||||||
|
return !item->clipboardText().empty();
|
||||||
|
};
|
||||||
|
if (columnAlbum) {
|
||||||
|
const auto simple = !ranges::any_of(group->items, hasCaption);
|
||||||
|
if (!simple) {
|
||||||
|
auto result = TextForMimeData();
|
||||||
|
for (const auto &item : group->items) {
|
||||||
|
if (result.empty()) {
|
||||||
|
result = HistoryItemText(item);
|
||||||
|
} else {
|
||||||
|
result.append(qstr("\n\n")).append(HistoryItemText(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
auto caption = [&] {
|
auto caption = [&] {
|
||||||
auto &&nonempty = ranges::view::all(
|
auto &&nonempty = ranges::view::all(
|
||||||
group->items
|
group->items
|
||||||
) | ranges::view::filter([](not_null<HistoryItem*> item) {
|
) | ranges::view::filter(
|
||||||
return !item->clipboardText().empty();
|
hasCaption
|
||||||
}) | ranges::view::take(2);
|
) | ranges::view::take(2);
|
||||||
auto first = nonempty.begin();
|
auto first = nonempty.begin();
|
||||||
auto end = nonempty.end();
|
auto end = nonempty.end();
|
||||||
if (first == end) {
|
if (first == end) {
|
||||||
|
|
|
@ -908,8 +908,7 @@ void Document::drawGrouped(
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache,
|
not_null<QPixmap*> cache) const {
|
||||||
bool last) const {
|
|
||||||
p.translate(geometry.topLeft());
|
p.translate(geometry.topLeft());
|
||||||
draw(
|
draw(
|
||||||
p,
|
p,
|
||||||
|
@ -924,8 +923,7 @@ TextState Document::getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request) const {
|
||||||
bool last) const {
|
|
||||||
point -= geometry.topLeft();
|
point -= geometry.topLeft();
|
||||||
return textState(
|
return textState(
|
||||||
point,
|
point,
|
||||||
|
|
|
@ -73,14 +73,12 @@ public:
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache,
|
not_null<QPixmap*> cache) const override;
|
||||||
bool last) const override;
|
|
||||||
TextState getStateGrouped(
|
TextState getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request) const override;
|
||||||
bool last) const override;
|
|
||||||
|
|
||||||
bool voiceProgressAnimationCallback(crl::time now);
|
bool voiceProgressAnimationCallback(crl::time now);
|
||||||
|
|
||||||
|
|
|
@ -902,8 +902,7 @@ void Gif::drawGrouped(
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache,
|
not_null<QPixmap*> cache) const {
|
||||||
bool last) const {
|
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
const auto item = _parent->data();
|
const auto item = _parent->data();
|
||||||
const auto loaded = dataLoaded();
|
const auto loaded = dataLoaded();
|
||||||
|
@ -1091,8 +1090,7 @@ TextState Gif::getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request) const {
|
||||||
bool last) const {
|
|
||||||
if (!geometry.contains(point)) {
|
if (!geometry.contains(point)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,14 +80,12 @@ public:
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache,
|
not_null<QPixmap*> cache) const override;
|
||||||
bool last) const override;
|
|
||||||
TextState getStateGrouped(
|
TextState getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request) const override;
|
||||||
bool last) const override;
|
|
||||||
|
|
||||||
void stopAnimation() override;
|
void stopAnimation() override;
|
||||||
void checkAnimation() override;
|
void checkAnimation() override;
|
||||||
|
|
|
@ -182,8 +182,7 @@ TextState Media::getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request) const {
|
||||||
bool last) const {
|
|
||||||
Unexpected("Grouping method call.");
|
Unexpected("Grouping method call.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,16 +178,14 @@ public:
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache,
|
not_null<QPixmap*> cache) const {
|
||||||
bool last) const {
|
|
||||||
Unexpected("Grouping method call.");
|
Unexpected("Grouping method call.");
|
||||||
}
|
}
|
||||||
[[nodiscard]] virtual TextState getStateGrouped(
|
[[nodiscard]] virtual TextState getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request) const;
|
||||||
bool last) const;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual bool animating() const {
|
[[nodiscard]] virtual bool animating() const {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -254,14 +254,21 @@ void GroupedMedia::draw(
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
crl::time ms) const {
|
crl::time ms) const {
|
||||||
const auto groupPadding = groupedPadding();
|
const auto groupPadding = groupedPadding();
|
||||||
|
const auto fullSelection = (selection == FullSelection);
|
||||||
|
const auto textSelection = !fullSelection
|
||||||
|
&& !IsSubGroupSelection(selection);
|
||||||
for (auto i = 0, count = int(_parts.size()); i != count; ++i) {
|
for (auto i = 0, count = int(_parts.size()); i != count; ++i) {
|
||||||
const auto &part = _parts[i];
|
const auto &part = _parts[i];
|
||||||
const auto partSelection = (selection == FullSelection)
|
const auto partSelection = fullSelection
|
||||||
? FullSelection
|
? FullSelection
|
||||||
|
: textSelection
|
||||||
|
? selection
|
||||||
: IsGroupItemSelection(selection, i)
|
: IsGroupItemSelection(selection, i)
|
||||||
? FullSelection
|
? FullSelection
|
||||||
: TextSelection();
|
: TextSelection();
|
||||||
const auto last = (i + 1 == count);
|
if (textSelection) {
|
||||||
|
selection = part.content->skipSelection(selection);
|
||||||
|
}
|
||||||
part.content->drawGrouped(
|
part.content->drawGrouped(
|
||||||
p,
|
p,
|
||||||
clip,
|
clip,
|
||||||
|
@ -271,8 +278,7 @@ void GroupedMedia::draw(
|
||||||
part.sides,
|
part.sides,
|
||||||
cornersFromSides(part.sides),
|
cornersFromSides(part.sides),
|
||||||
&part.cacheKey,
|
&part.cacheKey,
|
||||||
&part.cache,
|
&part.cache);
|
||||||
last);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// date
|
// date
|
||||||
|
@ -303,20 +309,19 @@ void GroupedMedia::draw(
|
||||||
TextState GroupedMedia::getPartState(
|
TextState GroupedMedia::getPartState(
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const {
|
StateRequest request) const {
|
||||||
auto index = 0;
|
auto shift = 0;
|
||||||
for (const auto &part : _parts) {
|
for (const auto &part : _parts) {
|
||||||
++index;
|
|
||||||
if (part.geometry.contains(point)) {
|
if (part.geometry.contains(point)) {
|
||||||
const auto last = (index == _parts.size());
|
|
||||||
auto result = part.content->getStateGrouped(
|
auto result = part.content->getStateGrouped(
|
||||||
part.geometry,
|
part.geometry,
|
||||||
part.sides,
|
part.sides,
|
||||||
point,
|
point,
|
||||||
request,
|
request);
|
||||||
last);
|
result.symbol += shift;
|
||||||
result.itemId = part.item->fullId();
|
result.itemId = part.item->fullId();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
shift += part.content->fullSelectionLength();
|
||||||
}
|
}
|
||||||
return TextState(_parent->data());
|
return TextState(_parent->data());
|
||||||
}
|
}
|
||||||
|
@ -389,12 +394,69 @@ bool GroupedMedia::dragItemByHandler(const ClickHandlerPtr &p) const {
|
||||||
TextSelection GroupedMedia::adjustSelection(
|
TextSelection GroupedMedia::adjustSelection(
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
TextSelectType type) const {
|
TextSelectType type) const {
|
||||||
return _caption.adjustSelection(selection, type);
|
if (_mode != Mode::Column) {
|
||||||
|
return _caption.adjustSelection(selection, type);
|
||||||
|
}
|
||||||
|
auto checked = 0;
|
||||||
|
for (const auto &part : _parts) {
|
||||||
|
const auto modified = ShiftItemSelection(
|
||||||
|
part.content->adjustSelection(
|
||||||
|
UnshiftItemSelection(selection, checked),
|
||||||
|
type),
|
||||||
|
checked);
|
||||||
|
const auto till = checked + part.content->fullSelectionLength();
|
||||||
|
if (selection.from >= checked && selection.from < till) {
|
||||||
|
selection.from = modified.from;
|
||||||
|
}
|
||||||
|
if (selection.to <= till) {
|
||||||
|
selection.to = modified.to;
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 GroupedMedia::fullSelectionLength() const {
|
||||||
|
if (_mode != Mode::Column) {
|
||||||
|
return _caption.length();
|
||||||
|
}
|
||||||
|
auto result = 0;
|
||||||
|
for (const auto &part : _parts) {
|
||||||
|
result += part.content->fullSelectionLength();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GroupedMedia::hasTextForCopy() const {
|
||||||
|
if (_mode != Mode::Column) {
|
||||||
|
return !_caption.isEmpty();
|
||||||
|
}
|
||||||
|
for (const auto &part : _parts) {
|
||||||
|
if (part.content->hasTextForCopy()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextForMimeData GroupedMedia::selectedText(
|
TextForMimeData GroupedMedia::selectedText(
|
||||||
TextSelection selection) const {
|
TextSelection selection) const {
|
||||||
return _caption.toTextForMimeData(selection);
|
if (_mode != Mode::Column) {
|
||||||
|
return _caption.toTextForMimeData(selection);
|
||||||
|
}
|
||||||
|
auto result = TextForMimeData();
|
||||||
|
for (const auto &part : _parts) {
|
||||||
|
auto text = part.content->selectedText(selection);
|
||||||
|
if (!text.empty()) {
|
||||||
|
if (result.empty()) {
|
||||||
|
result = std::move(text);
|
||||||
|
} else {
|
||||||
|
result.append(qstr("\n\n")).append(std::move(text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selection = part.content->skipSelection(selection);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GroupedMedia::getBubbleSelectionIntervals(
|
auto GroupedMedia::getBubbleSelectionIntervals(
|
||||||
|
|
|
@ -48,12 +48,8 @@ public:
|
||||||
[[nodiscard]] TextSelection adjustSelection(
|
[[nodiscard]] TextSelection adjustSelection(
|
||||||
TextSelection selection,
|
TextSelection selection,
|
||||||
TextSelectType type) const override;
|
TextSelectType type) const override;
|
||||||
uint16 fullSelectionLength() const override {
|
uint16 fullSelectionLength() const override;
|
||||||
return _caption.length();
|
bool hasTextForCopy() const override;
|
||||||
}
|
|
||||||
bool hasTextForCopy() const override {
|
|
||||||
return !_caption.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
PhotoData *getPhoto() const override;
|
PhotoData *getPhoto() const override;
|
||||||
DocumentData *getDocument() const override;
|
DocumentData *getDocument() const override;
|
||||||
|
|
|
@ -486,8 +486,7 @@ void Photo::drawGrouped(
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache,
|
not_null<QPixmap*> cache) const {
|
||||||
bool last) const {
|
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
_dataMedia->automaticLoad(_realParent->fullId(), _parent->data());
|
_dataMedia->automaticLoad(_realParent->fullId(), _parent->data());
|
||||||
|
|
||||||
|
@ -587,8 +586,7 @@ TextState Photo::getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request) const {
|
||||||
bool last) const {
|
|
||||||
if (!geometry.contains(point)) {
|
if (!geometry.contains(point)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,14 +69,12 @@ public:
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
RectParts corners,
|
RectParts corners,
|
||||||
not_null<uint64*> cacheKey,
|
not_null<uint64*> cacheKey,
|
||||||
not_null<QPixmap*> cache,
|
not_null<QPixmap*> cache) const override;
|
||||||
bool last) const override;
|
|
||||||
TextState getStateGrouped(
|
TextState getStateGrouped(
|
||||||
const QRect &geometry,
|
const QRect &geometry,
|
||||||
RectParts sides,
|
RectParts sides,
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request,
|
StateRequest request) const override;
|
||||||
bool last) const override;
|
|
||||||
|
|
||||||
TextWithEntities getCaption() const override {
|
TextWithEntities getCaption() const override {
|
||||||
return _caption.toTextWithEntities();
|
return _caption.toTextWithEntities();
|
||||||
|
|
Loading…
Add table
Reference in a new issue