Skip to content

Commit

Permalink
Google Workspace: Add file path information (#14888)
Browse files Browse the repository at this point in the history
* Update google-workspace extension

* Update google-workspace extension

* Update google-workspace extension

* Update google-workspace extension

* Update google-workspace extension

* Fix a few things

* Update CHANGELOG.md and optimise images

---------

Co-authored-by: Thomas Lombart <[email protected]>
Co-authored-by: raycastbot <[email protected]>
  • Loading branch information
3 people authored Oct 21, 2024
1 parent c19cab6 commit 3307856
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 42 deletions.
4 changes: 4 additions & 0 deletions extensions/google-workspace/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Google Workspace Changelog

## [Add file path info to the file list] - 2024-10-21

- Adds the file path information to the list of accessories.

## [Log out the user if re-authentication fails] - 2024-07-11

- Automatically log out users if re-authentication fails, instead of displaying an error message.
Expand Down
13 changes: 12 additions & 1 deletion extensions/google-workspace/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,23 @@
"mathieudutour",
"marcmagn1",
"meganpearson",
"jbjanot"
"jbjanot",
"ridemountainpig"
],
"categories": [
"Productivity"
],
"license": "MIT",
"preferences": [
{
"name": "displayFilePath",
"type": "checkbox",
"required": false,
"default": false,
"description": "Display the file path in the search results. ⚠️ This may slow down your search results.",
"label": "Display file path in search results"
}
],
"commands": [
{
"name": "create-google-document",
Expand Down
66 changes: 62 additions & 4 deletions extensions/google-workspace/src/api/getFiles.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { getOAuthToken } from "./googleAuth";
import { getPreferenceValues } from "@raycast/api";
import fetch from "node-fetch";

export enum QueryTypes {
fileName = "fileName",
fullText = "fullText",
Expand All @@ -19,11 +23,18 @@ export type File = {
modifiedTime: string;
starred: boolean;
parents?: string[];
filePath?: string;
capabilities?: {
canTrash: boolean;
};
};

type FileData = {
id: string;
name: string;
parents: string[];
};

function getParams(queryType: QueryTypes, scope: ScopeTypes, queryText = "") {
const params = new URLSearchParams();

Expand Down Expand Up @@ -57,10 +68,57 @@ function getParams(queryType: QueryTypes, scope: ScopeTypes, queryText = "") {
return params.toString();
}

export function getFilesURL(queryType: QueryTypes, scope: ScopeTypes, queryText = "") {
return `https://www.googleapis.com/drive/v3/files?${getParams(queryType, scope, queryText)}`;
export async function getFiles(queryType: QueryTypes, scope: ScopeTypes, queryText = "") {
const url = `https://www.googleapis.com/drive/v3/files?${getParams(queryType, scope, queryText)}`;
const response = await fetch(url, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getOAuthToken()}`,
},
});
const data = (await response.json()) as { files: File[] };

const { displayFilePath } = getPreferenceValues<Preferences>();
if (displayFilePath) {
await Promise.all(
data.files.map(async (file) => {
file.filePath = await getFilePath(file.id);
}),
);
}

return data;
}

async function getFilePath(fileId: string): Promise<string> {
const getFileParents = async (fileId: string) => {
const getFileUrl = `https://www.googleapis.com/drive/v3/files/${fileId}?fields=name,parents`;
const response = await fetch(getFileUrl, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getOAuthToken()}`,
},
});

return await response.json();
};

const getParentPath = async (fileId: string): Promise<string> => {
const fileData = (await getFileParents(fileId)) as FileData;

if (!fileData.parents || fileData.parents.length === 0) {
return fileData.name;
}

const parentId = fileData.parents[0];
const parentPath = await getParentPath(parentId);

return `${parentPath}/${fileData.name}`;
};

return await getParentPath(fileId);
}

export function getStarredFilesURL() {
return getFilesURL(QueryTypes.starred, ScopeTypes.allDrives);
export function getStarredFiles() {
return getFiles(QueryTypes.starred, ScopeTypes.allDrives);
}
10 changes: 9 additions & 1 deletion extensions/google-workspace/src/components/FileListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Action, ActionPanel, Color, Icon, List } from "@raycast/api";
import { Action, ActionPanel, Color, Icon, List, getPreferenceValues } from "@raycast/api";
import { format } from "date-fns";
import { File } from "../api/getFiles";
import { getFileIconLink, humanFileSize } from "../helpers/files";
Expand All @@ -9,6 +9,7 @@ type FileListItemProps = {
};

export default function FileListItem({ file, email }: FileListItemProps) {
const { displayFilePath } = getPreferenceValues();
const modifiedTime = new Date(file.modifiedTime);

const accessories: List.Item.Accessory[] = [
Expand All @@ -18,6 +19,13 @@ export default function FileListItem({ file, email }: FileListItemProps) {
},
];

if (displayFilePath && file.filePath) {
accessories.unshift({
icon: { source: Icon.Folder, tintColor: Color.SecondaryText },
tooltip: file.filePath,
});
}

if (file.starred) {
accessories.unshift({
icon: { source: Icon.Star, tintColor: Color.Yellow },
Expand Down
24 changes: 9 additions & 15 deletions extensions/google-workspace/src/search-google-drive-files.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Action, ActionPanel, List, showToast, Toast } from "@raycast/api";
import { useFetch, useCachedState } from "@raycast/utils";
import { Action, ActionPanel, List } from "@raycast/api";
import { useCachedPromise, useCachedState } from "@raycast/utils";
import { useState } from "react";

import { QueryTypes, getFilesURL, File, ScopeTypes } from "./api/getFiles";
import { QueryTypes, getFiles, ScopeTypes } from "./api/getFiles";
import FileListItem from "./components/FileListItem";

import { withGoogleAuth } from "./components/withGoogleAuth";
import { getOAuthToken, getUserEmail } from "./api/googleAuth";
import { getUserEmail } from "./api/googleAuth";

function SearchGoogleDriveFiles() {
const [query, setQuery] = useState("");
Expand All @@ -15,17 +15,11 @@ function SearchGoogleDriveFiles() {

const email = getUserEmail();

const { data, isLoading } = useFetch<{ files: File[] }>(getFilesURL(queryType, scopeType, query), {
keepPreviousData: true,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getOAuthToken()}`,
},
onError(error) {
console.error(error);
showToast({ style: Toast.Style.Failure, title: "Failed to retrieve files" });
},
});
const { data, isLoading } = useCachedPromise(
async (queryType: QueryTypes, scopeType: ScopeTypes, query: string) => await getFiles(queryType, scopeType, query),
[queryType, scopeType, query],
{ failureToastOptions: { title: "Failed to retrieve files" } },
);

return (
<List
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { Icon, LaunchType, MenuBarExtra, launchCommand, open } from "@raycast/api";
import { useFetch } from "@raycast/utils";
import { File, getStarredFilesURL } from "./api/getFiles";
import { useCachedPromise } from "@raycast/utils";
import { getStarredFiles } from "./api/getFiles";
import { withGoogleAuth } from "./components/withGoogleAuth";
import { getFileIconLink } from "./helpers/files";
import { createDocFromUrl } from "./helpers/docs";
import { getOAuthToken } from "./api/googleAuth";

function StarredFiles() {
const { data, isLoading } = useFetch<{ files: File[] }>(getStarredFilesURL(), {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getOAuthToken()}`,
},
const { data, isLoading } = useCachedPromise(async () => {
try {
return await getStarredFiles();
} catch (error) {
console.error(error);
throw error;
}
});

const MAX_ITEMS = 40;
Expand Down
19 changes: 6 additions & 13 deletions extensions/google-workspace/src/starred-google-drive-files.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import { Action, ActionPanel, List, showToast, Toast } from "@raycast/api";
import { useFetch } from "@raycast/utils";
import { Action, ActionPanel, List } from "@raycast/api";
import { useCachedPromise } from "@raycast/utils";

import { getStarredFilesURL, File } from "./api/getFiles";
import { getStarredFiles } from "./api/getFiles";
import FileListItem from "./components/FileListItem";
import { withGoogleAuth } from "./components/withGoogleAuth";
import { getOAuthToken, getUserEmail } from "./api/googleAuth";
import { getUserEmail } from "./api/googleAuth";

function StarredGoogleDriveFiles() {
const email = getUserEmail();

const { data, isLoading } = useFetch<{ files: File[] }>(getStarredFilesURL(), {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getOAuthToken()}`,
},
onError(error) {
console.error(error);
showToast({ style: Toast.Style.Failure, title: "Failed to retrieve starred files" });
},
const { data, isLoading } = useCachedPromise(() => getStarredFiles(), [], {
failureToastOptions: { title: "Failed to retrieve starred files" },
});

return (
Expand Down

0 comments on commit 3307856

Please sign in to comment.