Skip to content

Commit

Permalink
Jump to line from push notification
Browse files Browse the repository at this point in the history
Scrolling through unmeasured list items is difficult. However, by using
the onScrollToIndexFailed callback, it's possible to scroll between
measured list items, eventually landing at the target index.
Unfortunately it's a bit janky, but it works.

To ensure that all lines have been loaded before attempting to scroll to
the target line, lines are force reloaded for the current buffer before
attempting to scroll. When switching buffers, lines are (re)loaded as
normal via changeCurrentBuffer.

BufferContainer's componentDidUpdate will block scrolling until a state
flag is reset after the lines for the notified buffer are (re)loaded.
  • Loading branch information
mhoran committed Apr 10, 2024
1 parent 7efcabf commit 165a512
Show file tree
Hide file tree
Showing 11 changed files with 462 additions and 598 deletions.
25 changes: 9 additions & 16 deletions __tests__/lib/weechat/action_transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
fetchBuffersAction,
fetchBuffersRemovedAction
} from '../../../src/store/actions';
import { AppState } from '../../../src/store/app';

describe('transformToReduxAction', () => {
describe('on buffers', () => {
Expand All @@ -19,10 +20,8 @@ describe('transformToReduxAction', () => {
},
lines: { '8578d9c00': [], '83a41cd80': [] },
app: {
currentBufferId: '8578d9c00',
connected: true,
notificationBufferId: null
}
currentBufferId: '8578d9c00'
} as AppState
};
const store = configureStore({ reducer, preloadedState });

Expand Down Expand Up @@ -88,10 +87,8 @@ describe('transformToReduxAction', () => {
'83a41cd80': {} as WeechatBuffer
},
app: {
currentBufferId: '8578d9c00',
connected: true,
notificationBufferId: null
}
currentBufferId: '8578d9c00'
} as AppState
};
const store = configureStore({ reducer, preloadedState });

Expand Down Expand Up @@ -124,10 +121,8 @@ describe('transformToReduxAction', () => {
},
lines: { '8578d9c00': [], '83a41cd80': [] },
app: {
currentBufferId: '83a41cd80',
connected: true,
notificationBufferId: null
}
currentBufferId: '83a41cd80'
} as AppState
};
const store = configureStore({ reducer, preloadedState });

Expand Down Expand Up @@ -168,10 +163,8 @@ describe('transformToReduxAction', () => {
},
lines: { '8578d9c00': [], '83a41cd80': [] },
app: {
currentBufferId: '83a41cd80',
connected: true,
notificationBufferId: null
}
currentBufferId: '83a41cd80'
} as AppState
};
const store = configureStore({ reducer, preloadedState });

Expand Down
151 changes: 117 additions & 34 deletions __tests__/usecase/App.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,123 @@
import 'react-native';
import App from '../../src/usecase/App';

import { render } from '../../src/test-utils';

it('renders correctly', () => {
const tree = render(
<App
disconnect={() => {}}
fetchBufferInfo={() => {}}
sendMessageToBuffer={() => {}}
clearHotlistForBuffer={() => {}}
/>,
{
preloadedState: {
buffers: {
'8578d9c00': {
full_name: 'irc.libera.#weechat',
hidden: 0,
id: '8578d9c00',
local_variables: {
channel: '#weechat',
name: 'libera.#weechat',
plugin: 'irc',
type: 'channel'
},
notify: 3,
number: 2,
pointers: ['8578d9c00'],
short_name: '#weechat',
title: '',
type: 0
}
import { act, render } from '../../src/test-utils';
import { configureStore } from '@reduxjs/toolkit';
import { reducer } from '../../src/store';
import { AppState } from '../../src/store/app';
import { bufferNotificationAction } from '../../src/store/actions';

jest.mock('react-native-drawer-layout');

describe('App', () => {
describe('on notification', () => {
it('changes the current buffer to the notification buffer', () => {
const bufferId = '86c417600';
const store = configureStore({
reducer,
preloadedState: {
buffers: {
[bufferId]: {
full_name: 'irc.libera.#weechat',
hidden: 0,
id: bufferId,
local_variables: {
channel: '#weechat',
name: 'libera.#weechat',
plugin: 'irc',
type: 'channel'
},
notify: 3,
number: 2,
pointers: [bufferId],
short_name: '#weechat',
title: '',
type: 0
}
},
app: { currentBufferId: null } as AppState
}
}
}
);
});
const clearHotlistForBuffer = jest.fn();
const fetchBufferInfo = jest.fn();

render(
<App
disconnect={() => {}}
fetchBufferInfo={fetchBufferInfo}
sendMessageToBuffer={() => {}}
clearHotlistForBuffer={clearHotlistForBuffer}
/>,
{ store }
);

act(() => {
store.dispatch(
bufferNotificationAction({
bufferId,
lineId: '8580dcc40',
identifier: '1fb4fc1d-530b-466f-85be-de27772de0a9'
})
);
});

expect(store.getState().app.currentBufferId).toEqual(bufferId);
expect(clearHotlistForBuffer).toHaveBeenCalledWith(null);
expect(fetchBufferInfo).toHaveBeenCalledWith(bufferId);
});

it('fetches buffer info if the notification is for the current buffer', () => {
const bufferId = '86c417600';
const store = configureStore({
reducer,
preloadedState: {
buffers: {
[bufferId]: {
full_name: 'irc.libera.#weechat',
hidden: 0,
id: bufferId,
local_variables: {
channel: '#weechat',
name: 'libera.#weechat',
plugin: 'irc',
type: 'channel'
},
notify: 3,
number: 2,
pointers: [bufferId],
short_name: '#weechat',
title: '',
type: 0
}
},
app: { currentBufferId: bufferId } as AppState
}
});
const fetchBufferInfo = jest.fn();
const clearHotlistForBuffer = jest.fn();

render(
<App
disconnect={() => {}}
fetchBufferInfo={fetchBufferInfo}
sendMessageToBuffer={() => {}}
clearHotlistForBuffer={clearHotlistForBuffer}
/>,
{ store }
);

act(() => {
store.dispatch(
bufferNotificationAction({
bufferId,
lineId: '8580dcc40',
identifier: '1fb4fc1d-530b-466f-85be-de27772de0a9'
})
);
});

expect(tree).toMatchSnapshot();
expect(fetchBufferInfo).toHaveBeenCalledWith(bufferId);
expect(clearHotlistForBuffer).not.toHaveBeenCalled();
});
});
});
Loading

0 comments on commit 165a512

Please sign in to comment.