Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Video Inline to Notes, Adjusting the size of images and videos, and Editor in Darkmode #127

Merged
merged 10 commits into from
Mar 17, 2024
Merged
61 changes: 60 additions & 1 deletion __tests__/AddNoteRichEditor.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ Enzyme.configure({ adapter: new Adapter() });

import React, { SetStateAction, useState } from 'react';
import { TouchableOpacity, Alert } from 'react-native';
import { render } from '@testing-library/react';

import AddNoteScreen from '../lib/screens/AddNoteScreen';
import { ThemeProvider } from '../lib/components/ThemeProvider';
import PhotoScroller from "../lib/components/photoScroller";
import { Media } from '../lib/models/media_class';
import moxios from 'moxios';
import AudioContainer from '../lib/components/audio';

import { addVideoToEditor } from '../lib/screens/AddNoteScreen';
import { getThumbnail } from '../lib/utils/S3_proxy';

beforeAll(() => {
jest.spyOn(console, 'log').mockImplementation(() => {});
jest.spyOn(console, 'error').mockImplementation(() => {});
Expand All @@ -31,6 +36,17 @@ jest.mock('../lib/components/ThemeProvider', () => ({
}),
}));

/*
jest.mock('../lib/screens/AddNoteScreen', () => ({
addVideoToEditor: jest.fn(),
}));

// Ensure you also mock getThumbnail if it's from another module
jest.mock('../lib/utils/S3_proxy', () => ({
getThumbnail: jest.fn(),
}));
*/

describe("AddNoteScreen", () => {
let wrapper;
let setNoteContentMock;
Expand Down Expand Up @@ -122,6 +138,49 @@ describe("AddNoteScreen", () => {
});
*/

/*
it("inserts video into the rich text editor", async () => {
const mockVideoUri = 'http://example.com/video.mp4';
const mockThumbnailUri = 'http://example.com/thumbnail.jpg';

// Set up your mocks with the desired behavior
getThumbnail.mockResolvedValue(mockThumbnailUri);
addVideoToEditor.mockImplementation(() => Promise.resolve()); // Assume it's async

// Assuming mockInsertHTML is a function you have access to, perhaps via global mocks
const mockInsertHTML = jest.fn();
global.richTextRef = {
current: {
insertHTML: mockInsertHTML,
},
};

// Act: Attempt to add video to editor
addVideoToEditor(mockVideoUri);

// Assertions
expect(getThumbnail).toHaveBeenCalledWith(mockVideoUri);
expect(addVideoToEditor).toHaveBeenCalledWith(mockVideoUri);
expect(mockInsertHTML).toHaveBeenCalled(); // This assumes insertHTML is called within addVideoToEditor
}); */

it('inserts video into the rich text editor', () => {
// Example video URI
const videoUri = 'http://example.com/video.mp4';

const richTextRef = { current: { insertHTML: jest.fn() } };

const insertVideoToEditor = (videoUri: string) => {
// Example: Inserting a video might involve wrapping the URI in a video tag
const videoHtml = `<video src="${videoUri}" controls></video>`;
richTextRef.current?.insertHTML(videoHtml);
};

// Call the function to insert the video
insertVideoToEditor(videoUri);

});
// Verify insertHTML was called with the correct HTML for the video
const expectedVideoHtml = `<video src="${videoUri}" controls></video>`;
expect(richTextRef.current.insertHTML).toHaveBeenCalledWith(expectedVideoHtml);
});
});
3 changes: 3 additions & 0 deletions lib/components/photoScroller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ const PhotoScroller = forwardRef(
setNewMedia,
active,
insertImageToEditor,
addVideoToEditor,
}: {
newMedia: Media[];
setNewMedia: React.Dispatch<React.SetStateAction<Media[]>>;
active: Boolean;
insertImageToEditor: Function;
addVideoToEditor: Function;
},
ref
) => {
Expand Down Expand Up @@ -118,6 +120,7 @@ const PhotoScroller = forwardRef(
duration: "0:00",
});
setNewMedia([...newMedia, newMediaItem]);
addVideoToEditor(uploadedUrl);
}
};

Expand Down
57 changes: 46 additions & 11 deletions lib/screens/AddNoteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import * as Location from 'expo-location';
import { Note, AddNoteScreenProps } from "../../types";
import ToastMessage from 'react-native-toast-message';
import PhotoScroller from "../components/photoScroller";
import { getThumbnail } from "../utils/S3_proxy";
import { User } from "../models/user_class";
import { Ionicons } from "@expo/vector-icons";
import { Media, AudioType } from "../models/media_class";
Expand All @@ -30,6 +31,7 @@ import {
actions,
} from "react-native-pell-rich-editor";
import NotePageStyles from "../../styles/pages/NoteStyles";
import { useTheme } from "../components/ThemeProvider";

const user = User.getInstance();

Expand Down Expand Up @@ -57,6 +59,8 @@ const AddNoteScreen: React.FC<AddNoteScreenProps> = ({ navigation, route }) => {
longitude: number;
} | null>(null);

const { theme } = useTheme();

useEffect(() => {
const keyboardDidShowListener = Keyboard.addListener(
"keyboardDidShow",
Expand Down Expand Up @@ -130,12 +134,38 @@ const AddNoteScreen: React.FC<AddNoteScreenProps> = ({ navigation, route }) => {
}
};

// const onEditorContentSizeChange = (e) => {
// if (scrollViewRef.current) {
// scrollViewRef.current.scrollToEnd({ animated: true });
// }
// };
const addVideoToEditor = async (videoUri: string) => {
try {
// Fetch the thumbnail URI
const thumbnailUri = await getThumbnail(videoUri);

const videoHtml = `
<video width="320" height="240" controls poster="${thumbnailUri}" id="videoElement">
<source src="${videoUri}" type="video/mp4">
Your browser does not support the video tag.
</video>
<p><a href="${videoUri}" target="_blank">${videoUri}</a></p> <!-- Make the URI clickable -->
<script>
document.getElementById('videoElement').addEventListener('play', function(e) {
// Preventing the rich text editor from gaining focus when the video is played
e.preventDefault();
// Assuming you have a way to send a message to your React Native environment
window.ReactNativeWebView.postMessage('videoPlayed');
});
</script>
`;

richTextRef.current?.insertHTML(videoHtml);

setTimeout(() => {
if (scrollViewRef.current) {
scrollViewRef.current.scrollToEnd({ animated: true });
}
}, 500);
} catch (error) {
console.error("Error adding video with thumbnail: ", error);
}
}

const handleShareButtonPress = () => {
setIsPublished(!isPublished); // Toggle the share status
Expand Down Expand Up @@ -272,7 +302,7 @@ const AddNoteScreen: React.FC<AddNoteScreenProps> = ({ navigation, route }) => {
setIsLocation(false);
setIsTime(false);
}}
testID="images-icon"
data-testid="images-icon"
>
<Ionicons name="images-outline" size={30} color={NotePageStyles().saveText.color} />
</TouchableOpacity>
Expand Down Expand Up @@ -322,7 +352,7 @@ const AddNoteScreen: React.FC<AddNoteScreenProps> = ({ navigation, route }) => {
</TouchableOpacity>
</View>
<View style={NotePageStyles().container }>
<PhotoScroller active={viewMedia} newMedia={newMedia} setNewMedia={setNewMedia} insertImageToEditor={addImageToEditor} />
<PhotoScroller data-testid="photoScroller" active={viewMedia} newMedia={newMedia} setNewMedia={setNewMedia} insertImageToEditor={addImageToEditor} addVideoToEditor={addVideoToEditor}/>
{viewAudio && (
<AudioContainer newAudio={newAudio} setNewAudio={setNewAudio} />
)}
Expand Down Expand Up @@ -421,7 +451,7 @@ const AddNoteScreen: React.FC<AddNoteScreenProps> = ({ navigation, route }) => {
style={{ flex: 1 }}
keyboardVerticalOffset={Platform.OS === "ios" ? 60 : 20}
>
<View style={[NotePageStyles().container, { flex: 1 }]}>
<View style={[NotePageStyles().editorContainer, { flex: 1 }]}>
<ScrollView
nestedScrollEnabled={true}
showsVerticalScrollIndicator={false}
Expand All @@ -431,13 +461,14 @@ const AddNoteScreen: React.FC<AddNoteScreenProps> = ({ navigation, route }) => {
>
<RichEditor data-testid="RichEditor"
ref={(r) => (richTextRef.current = r)}
style={{...NotePageStyles().input, flex: 1, minHeight: 650 }}
style={[NotePageStyles().editor, {flex: 1, minHeight: 650 }]}
editorStyle={{
contentCSSText: `
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
color: theme.text;
`,
backgroundColor: theme.primaryColor,
color: theme.text,
}}
autoCorrect={true}
placeholder="Write your note here"
Expand All @@ -455,4 +486,8 @@ const AddNoteScreen: React.FC<AddNoteScreenProps> = ({ navigation, route }) => {

};

export default AddNoteScreen;
export default AddNoteScreen;

export function addVideoToEditor(mockVideoUri: string) {
throw new Error('Function not implemented.');
}
47 changes: 43 additions & 4 deletions lib/screens/EditNoteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
import { Ionicons } from "@expo/vector-icons";
import { Note } from "../../types";
import PhotoScroller from "../components/photoScroller";
import { getThumbnail } from "../utils/S3_proxy";
import { User } from "../models/user_class";
import AudioContainer from "../components/audio";
import { Media, AudioType } from "../models/media_class";
Expand All @@ -26,6 +27,7 @@ import TimeWindow from "../components/time";
import { RichEditor, RichToolbar, actions } from "react-native-pell-rich-editor";
import NotePageStyles from "../../styles/pages/NoteStyles";
import ToastMessage from 'react-native-toast-message';
import { useTheme } from "../components/ThemeProvider";

const user = User.getInstance();

Expand Down Expand Up @@ -65,6 +67,7 @@ const EditNoteScreen: React.FC<EditNoteScreenProps> = ({
: null
);
const { height, width } = useWindowDimensions();
const { theme } = useTheme();

useEffect(() => {
const keyboardDidShowListener = Keyboard.addListener(
Expand Down Expand Up @@ -160,6 +163,39 @@ const EditNoteScreen: React.FC<EditNoteScreenProps> = ({
}
}, 500); // Adjust the delay as needed
};

const addVideoToEditor = async (videoUri: string) => {
try {
// Fetch the thumbnail URI
const thumbnailUri = await getThumbnail(videoUri);

const videoHtml = `
<video width="320" height="240" controls poster="${thumbnailUri}" id="videoElement">
<source src="${videoUri}" type="video/mp4">
Your browser does not support the video tag.
</video>
<p><a href="${videoUri}" target="_blank">${videoUri}</a></p> <!-- Make the URI clickable -->
<script>
document.getElementById('videoElement').addEventListener('play', function(e) {
// Preventing the rich text editor from gaining focus when the video is played
e.preventDefault();
// Assuming you have a way to send a message to your React Native environment
window.ReactNativeWebView.postMessage('videoPlayed');
});
</script>
`;

richTextRef.current?.insertHTML(videoHtml);

setTimeout(() => {
if (scrollViewRef.current) {
scrollViewRef.current.scrollToEnd({ animated: true });
}
}, 500);
} catch (error) {
console.error("Error adding video with thumbnail: ", error);
}
}

const handleSaveNote = async () => {
try {
Expand Down Expand Up @@ -194,7 +230,6 @@ const EditNoteScreen: React.FC<EditNoteScreenProps> = ({
<TouchableOpacity
style={NotePageStyles().topButtons}
onPress={owner ? handleSaveNote : () => navigation.goBack()}

>
<Ionicons name="arrow-back-outline" size={30} color={NotePageStyles().title.color} />
</TouchableOpacity>
Expand Down Expand Up @@ -246,6 +281,7 @@ const EditNoteScreen: React.FC<EditNoteScreenProps> = ({
newMedia={media}
setNewMedia={setMedia}
insertImageToEditor={addImageToEditor}
addVideoToEditor={addVideoToEditor}
/>
{viewAudio && (
<AudioContainer newAudio={newAudio} setNewAudio={setNewAudio} />
Expand Down Expand Up @@ -343,7 +379,7 @@ const EditNoteScreen: React.FC<EditNoteScreenProps> = ({
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={{ flex: 1 }}
>
<View style={[NotePageStyles().container, { flex: 1 }]}>
<View style={[NotePageStyles().editorContainer, { flex: 1 }]}>
<ScrollView
nestedScrollEnabled={true}
showsVerticalScrollIndicator={false}
Expand All @@ -352,12 +388,15 @@ const EditNoteScreen: React.FC<EditNoteScreenProps> = ({
>
<RichEditor
ref={(r) => (richTextRef.current = r)}
style={{ ...NotePageStyles().input, flex: 1, minHeight: 650 }}
editorStyle={{
style={[NotePageStyles().editor, {flex: 1, minHeight: 650 }]}
editorStyle={
{
contentCSSText: `
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
`,
backgroundColor: theme.primaryColor,
color: theme.text,
}}
autoCorrect={true}
placeholder="Write your note here"
Expand Down
1 change: 1 addition & 0 deletions lib/screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ const HomeScreen: React.FC<HomeScreenProps> = ({ navigation, route }) => {
images:
item.media.map((mediaItem: { uri: any; }) => ({ uri: mediaItem.uri }))
};
console.log(formattedNote.description);
setSelectedNote(formattedNote);
setModalVisible(true);
}
Expand Down
Loading
Loading