Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Poll history: fetch more poll history #10235

Merged
merged 11 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions res/css/views/dialogs/polls/_PollHistoryList.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,20 @@ limitations under the License.
.mx_PollHistoryList_noResults {
height: 100%;
width: 100%;
box-sizing: border-box;
padding: 0 $spacing-64;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;

line-height: $font-24px;
color: $secondary-content;

.mx_PollHistoryList_loadMorePolls {
margin-top: $spacing-16;
}
}

.mx_PollHistoryList_loading {
Expand All @@ -57,3 +67,7 @@ limitations under the License.
margin: auto auto;
}
}

.mx_PollHistoryList_loadMorePolls {
width: max-content;
}
6 changes: 4 additions & 2 deletions src/components/views/dialogs/polls/PollHistoryDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ export const PollHistoryDialog: React.FC<PollHistoryDialogProps> = ({
onFinished,
}) => {
const { polls } = usePollsWithRelations(room.roomId, matrixClient);
const { isLoading, loadMorePolls, oldestEventTimestamp } = useFetchPastPolls(room, matrixClient);
const [filter, setFilter] = useState<PollHistoryFilter>("ACTIVE");
const [focusedPollId, setFocusedPollId] = useState<string | null>(null);
const { isLoading } = useFetchPastPolls(room, matrixClient);

const pollStartEvents = filterAndSortPolls(polls, filter);
const isLoadingPollResponses = [...polls.values()].some((poll) => poll.isFetchingResponses);
Expand All @@ -78,12 +78,14 @@ export const PollHistoryDialog: React.FC<PollHistoryDialogProps> = ({
<PollDetail poll={focusedPoll} permalinkCreator={permalinkCreator} requestModalClose={onFinished} />
) : (
<PollHistoryList
onItemClick={setFocusedPollId}
pollStartEvents={pollStartEvents}
isLoading={isLoading || isLoadingPollResponses}
oldestFetchedEventTimestamp={oldestEventTimestamp}
polls={polls}
filter={filter}
onFilterChange={setFilter}
onItemClick={setFocusedPollId}
loadMorePolls={loadMorePolls}
/>
)}
</div>
Expand Down
93 changes: 84 additions & 9 deletions src/components/views/dialogs/polls/PollHistoryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import InlineSpinner from "../../elements/InlineSpinner";
import { PollHistoryFilter } from "./types";
import { PollListItem } from "./PollListItem";
import { PollListItemEnded } from "./PollListItemEnded";
import AccessibleButton from "../../elements/AccessibleButton";

const LoadingPolls: React.FC<{ noResultsYet?: boolean }> = ({ noResultsYet }) => (
<div
Expand All @@ -36,20 +37,93 @@ const LoadingPolls: React.FC<{ noResultsYet?: boolean }> = ({ noResultsYet }) =>
</div>
);

const LoadMorePolls: React.FC<{ loadMorePolls?: () => void; isLoading?: boolean }> = ({ isLoading, loadMorePolls }) =>
loadMorePolls ? (
<AccessibleButton
className="mx_PollHistoryList_loadMorePolls"
kind="link_inline"
onClick={() => loadMorePolls()}
>
{_t("Load more polls")}
{isLoading && <InlineSpinner />}
</AccessibleButton>
) : null;

const ONE_DAY_MS = 60000 * 60 * 24;
const getNoResultsMessage = (
filter: PollHistoryFilter,
oldestEventTimestamp?: number,
loadMorePolls?: () => void,
): string => {
if (!loadMorePolls) {
return filter === "ACTIVE"
? _t("There are no active polls in this room")
: _t("There are no past polls in this room");
}

// we don't know how much history has been fetched
if (!oldestEventTimestamp) {
return filter === "ACTIVE"
? _t("There are no active polls. Load more polls to view polls for previous months")
: _t("There are no past polls. Load more polls to view polls for previous months");
}

const fetchedHistoryDaysCount = Math.ceil((Date.now() - oldestEventTimestamp) / ONE_DAY_MS);
return filter === "ACTIVE"
? _t(
"There are no active polls for the past %(count)s days. Load more polls to view polls for previous months",
{ count: fetchedHistoryDaysCount },
)
: _t("There are no past polls for the past %(count)s days. Load more polls to view polls for previous months", {
count: fetchedHistoryDaysCount,
});
};

const NoResults: React.FC<{
filter: PollHistoryFilter;
oldestFetchedEventTimestamp?: number;
loadMorePolls?: () => void;
isLoading?: boolean;
}> = ({ filter, isLoading, oldestFetchedEventTimestamp, loadMorePolls }) => {
// we can't page the timeline anymore
// just use plain loader
if (!loadMorePolls && isLoading) {
return <LoadingPolls noResultsYet />;
}

return (
<span className="mx_PollHistoryList_noResults">
{getNoResultsMessage(filter, oldestFetchedEventTimestamp, loadMorePolls)}

{!!loadMorePolls && <LoadMorePolls loadMorePolls={loadMorePolls} isLoading={isLoading} />}
</span>
);
};

type PollHistoryListProps = {
pollStartEvents: MatrixEvent[];
polls: Map<string, Poll>;
filter: PollHistoryFilter;
isLoading?: boolean;
/**
* server ts of the oldest fetched poll
* ignoring filter
* used to render no results in last x days message
* undefined when no polls are found
*/
oldestFetchedEventTimestamp?: number;
onFilterChange: (filter: PollHistoryFilter) => void;
onItemClick: (pollId: string) => void;
loadMorePolls?: () => void;
isLoading?: boolean;
};
export const PollHistoryList: React.FC<PollHistoryListProps> = ({
pollStartEvents,
polls,
filter,
isLoading,
oldestFetchedEventTimestamp,
onFilterChange,
loadMorePolls,
onItemClick,
}) => {
return (
Expand Down Expand Up @@ -81,17 +155,18 @@ export const PollHistoryList: React.FC<PollHistoryListProps> = ({
/>
),
)}
{isLoading && <LoadingPolls />}
{isLoading && !loadMorePolls && <LoadingPolls />}
{!!loadMorePolls && <LoadMorePolls loadMorePolls={loadMorePolls} isLoading={isLoading} />}
</ol>
)}
{!pollStartEvents.length && !isLoading && (
<span className="mx_PollHistoryList_noResults">
{filter === "ACTIVE"
? _t("There are no active polls in this room")
: _t("There are no past polls in this room")}
</span>
{!pollStartEvents.length && (
<NoResults
oldestFetchedEventTimestamp={oldestFetchedEventTimestamp}
isLoading={isLoading}
filter={filter}
loadMorePolls={loadMorePolls}
/>
)}
{!pollStartEvents.length && isLoading && <LoadingPolls noResultsYet />}
</div>
);
};
Loading