Skip to content

Commit

Permalink
feat: add observeScrollingInterval in coordinator plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
penfeizhou committed Mar 14, 2023
1 parent 7db5d68 commit 52e5977
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
import android.graphics.Color;
import android.view.View;

import com.github.pengfeizhou.jscore.JSArray;
import com.github.pengfeizhou.jscore.JSNumber;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue;
import com.github.pengfeizhou.jscore.JavaValue;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

import pub.doric.DoricContext;
Expand Down Expand Up @@ -173,4 +177,86 @@ private void setValue(ViewNode<?> viewNode, boolean isNavBar, String name, float
viewNode.blend(jsObject);
}
}


@DoricMethod(thread = ThreadMode.UI)
public void observeScrollingInterval(final JSObject argument, final DoricPromise doricPromise) {
getDoricContext().getDriver().asyncCall(new Callable<Object>() {
@Override
public Object call() throws Exception {
JSValue[] scrollableIds = argument.getProperty("scrollable").asArray().toArray();
ViewNode<?> scrollNode = null;
for (JSValue value : scrollableIds) {
if (scrollNode == null) {
scrollNode = getDoricContext().targetViewNode(value.asString().value());
} else {
if (value.isString() && scrollNode instanceof SuperNode) {
String viewId = value.asString().value();
scrollNode = ((SuperNode<?>) scrollNode).getSubNodeById(viewId);
}
}
}
if (scrollNode == null) {
throw new Exception("Cannot find scrollable view");
}
String callbackId = argument.getProperty("onScrolledInterval").asString().value();
final DoricPromise currentPromise = new DoricPromise(getDoricContext(), callbackId);
JSArray observingInterval = argument.getProperty("observingInterval").asArray();
final List<Float> interval = new ArrayList<>();
for (int i = 0; i < observingInterval.size(); i++) {
interval.add(observingInterval.get(i).asNumber().toFloat());
}

JSValue inclusive = argument.getProperty("inclusive");

final boolean leftInclusive = inclusive.isString() && "Left".equals(inclusive.asString().value());

final ViewNode<?> finalScrollNode = scrollNode;
final int[] rangeIdx = {0};
if (finalScrollNode instanceof IDoricScrollable) {
((IDoricScrollable) finalScrollNode).addScrollChangeListener(new DoricScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
int currentRangeIdx = interval.size();
for (int i = 0; i < interval.size(); i++) {
if (leftInclusive) {
if (scrollY < interval.get(i)) {
currentRangeIdx = i;
break;
}
} else {
if (scrollY <= interval.get(i)) {
currentRangeIdx = i;
break;
}
}
}
if (rangeIdx[0] != currentRangeIdx) {
rangeIdx[0] = currentRangeIdx;
currentPromise.resolve(new JavaValue(rangeIdx[0]));
}
}
});
return null;
} else {
throw new Exception("Scroller type error");
}
}
}, ThreadMode.UI).setCallback(new AsyncResult.Callback<Object>() {
@Override
public void onResult(Object result) {
doricPromise.resolve();
}

@Override
public void onError(Throwable t) {
doricPromise.reject();
}

@Override
public void onFinish() {

}
});
}
}
9 changes: 8 additions & 1 deletion doric-demo/src/ListDemo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Group, Panel, List, text, gravity, Color, LayoutSpec, list, listItem, log, vlayout, Gravity, hlayout, Text, refreshable, Refreshable, ListItem, layoutConfig, ViewHolder, ViewModel, VMPanel, loge, modal, stack } from "doric";
import { Group, Panel, List, text, gravity, Color, LayoutSpec, list, listItem, log, vlayout, Gravity, hlayout, Text, refreshable, Refreshable, ListItem, layoutConfig, ViewHolder, ViewModel, VMPanel, loge, modal, stack, coordinator } from "doric";

interface ItemModel {
text: string
Expand Down Expand Up @@ -64,6 +64,13 @@ class ListVH extends ViewHolder {

class ListVM extends ViewModel<ListModel, ListVH> {
onAttached(state: ListModel, vh: ListVH) {
coordinator(this.context).observeScrollingInterval({
scrollable: vh.list,
observingInterval: [0],
onScrolledInterval: (n) => {
console.log("onScrolledInterval", n)
}
});
vh.list.apply({
preloadItemCount: 5,
canDrag: true,
Expand Down
53 changes: 53 additions & 0 deletions doric-iOS/Pod/Classes/Plugin/DoricCoordinatorPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,57 @@ - (void)setValue:(DoricViewNode *)viewNode isNavBar:(BOOL)isNavBar name:(NSStrin
}
}

- (void)observeScrollingInterval:(NSDictionary *)params withPromise:(DoricPromise *)promise {
__weak typeof(self) _self = self;
[self.doricContext dispatchToMainQueue:^{
__strong typeof(_self) self = _self;
NSArray <NSString *> *scrollableIds = [params optArray:@"scrollable"];
DoricViewNode *scrollNode = nil;
for (NSString *value in scrollableIds) {
if (!scrollNode) {
scrollNode = [self.doricContext targetViewNode:value];
} else {
if ([scrollNode isKindOfClass:[DoricSuperNode class]]) {
scrollNode = [((DoricSuperNode *) scrollNode) subNodeWithViewId:value];
}
}
}
if (!scrollNode) {
[promise reject:@"Cannot find scrollable view"];
return;
}
NSString *callbackId = [params optString:@"onScrolledInterval"];
NSArray *observingInterval = [params optArray:@"observingInterval"];
DoricPromise *currentPromise = [[DoricPromise alloc] initWithContext:self.doricContext
callbackId:callbackId];
BOOL leftInclusive = [[params optString:@"inclusive"] isEqualToString:@"Left"];
if ([scrollNode conformsToProtocol:@protocol(DoricScrollableProtocol)]) {
__block NSUInteger rangeIdx = 0;
[(id <DoricScrollableProtocol>) scrollNode addDidScrollBlock:^(UIScrollView *scrollView) {
CGFloat scrollY = scrollView.contentOffset.y;
__block NSUInteger currentRangeIdx = observingInterval.count;
[observingInterval enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL *stop) {
if (leftInclusive) {
if (scrollY < obj.floatValue) {
currentRangeIdx = idx;
*stop = YES;
}
} else {
if (scrollY <= obj.floatValue) {
currentRangeIdx = idx;
*stop = YES;
}
}
}];
if (rangeIdx != currentRangeIdx) {
rangeIdx = currentRangeIdx;
[currentPromise resolve:@(rangeIdx)];
}
}];
} else {
[promise reject:@"Scroller type error"];
}
}];
}

@end
12 changes: 11 additions & 1 deletion doric-js/bundle/doric-lib.es5.js
Original file line number Diff line number Diff line change
Expand Up @@ -4597,7 +4597,17 @@ function coordinator(context) {
context.callNative("coordinator", "verticalScrolling", argument);
});
}
}
},
observeScrollingInterval: function (argument) {
if (context.entity instanceof Panel) {
var panel = context.entity;
panel.addOnRenderFinishedCallback(function () {
argument.scrollable = viewIdChains(argument.scrollable);
argument.onScrolledInterval = context.function2Id(argument.onScrolledInterval);
context.callNative("coordinator", "observeScrollingInterval", argument);
});
}
},
};
}

Expand Down
12 changes: 11 additions & 1 deletion doric-js/bundle/doric-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -3563,7 +3563,17 @@ function coordinator(context) {
context.callNative("coordinator", "verticalScrolling", argument);
});
}
}
},
observeScrollingInterval: (argument) => {
if (context.entity instanceof Panel) {
const panel = context.entity;
panel.addOnRenderFinishedCallback(() => {
argument.scrollable = viewIdChains(argument.scrollable);
argument.onScrolledInterval = context.function2Id(argument.onScrolledInterval);
context.callNative("coordinator", "observeScrollingInterval", argument);
});
}
},
};
}

Expand Down
12 changes: 11 additions & 1 deletion doric-js/bundle/doric-vm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5103,7 +5103,17 @@ function coordinator(context) {
context.callNative("coordinator", "verticalScrolling", argument);
});
}
}
},
observeScrollingInterval: (argument) => {
if (context.entity instanceof Panel) {
const panel = context.entity;
panel.addOnRenderFinishedCallback(() => {
argument.scrollable = viewIdChains(argument.scrollable);
argument.onScrolledInterval = context.function2Id(argument.onScrolledInterval);
context.callNative("coordinator", "observeScrollingInterval", argument);
});
}
},
};
}

Expand Down
6 changes: 6 additions & 0 deletions doric-js/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,12 @@ declare module "doric" {
end: number | Color;
};
}) => void;
observeScrollingInterval: (argument: {
scrollable: Scroller | List | FlowLayout;
observingInterval: number[];
inclusive?: "Left" | "Right" | undefined;
onScrolledInterval: (n: number) => void;
}) => void;
};
export function notch(context: BridgeContext): {
inset: () => Promise<{
Expand Down
6 changes: 6 additions & 0 deletions doric-js/lib/src/native/coordinator.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ export declare function coordinator(context: BridgeContext): {
end: number | Color;
};
}) => void;
observeScrollingInterval: (argument: {
scrollable: Scroller | List | FlowLayout;
observingInterval: number[];
inclusive?: "Left" | "Right" | undefined;
onScrolledInterval: (n: number) => void;
}) => void;
};
12 changes: 11 additions & 1 deletion doric-js/lib/src/native/coordinator.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ export function coordinator(context) {
context.callNative("coordinator", "verticalScrolling", argument);
});
}
}
},
observeScrollingInterval: (argument) => {
if (context.entity instanceof Panel) {
const panel = context.entity;
panel.addOnRenderFinishedCallback(() => {
argument.scrollable = viewIdChains(argument.scrollable);
argument.onScrolledInterval = context.function2Id(argument.onScrolledInterval);
context.callNative("coordinator", "observeScrollingInterval", argument);
});
}
},
};
}
40 changes: 32 additions & 8 deletions doric-js/src/native/coordinator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,45 @@ export function coordinator(context: BridgeContext) {
},
}) => {
if (context.entity instanceof Panel) {
const panel = context.entity
const panel = context.entity;
panel.addOnRenderFinishedCallback(() => {
(argument as any).scrollable = viewIdChains(argument.scrollable)
(argument as any).scrollable = viewIdChains(argument.scrollable);
if (argument.target instanceof View) {
(argument as any).target = viewIdChains(argument.target)
(argument as any).target = viewIdChains(argument.target);
}
if (argument.changing.start instanceof Color) {
argument.changing.start = argument.changing.start.toModel()
argument.changing.start = argument.changing.start.toModel();
}
if (argument.changing.end instanceof Color) {
argument.changing.end = argument.changing.end.toModel()
argument.changing.end = argument.changing.end.toModel();
}
context.callNative("coordinator", "verticalScrolling", argument)
})
context.callNative("coordinator", "verticalScrolling", argument);
});
}
}
},
observeScrollingInterval: (
argument: {
scrollable: Scroller | List | FlowLayout,
// [a_0, a_1, ...a_n] a_n-1<a_n
// It represents interval (-∞,a_0),(a_0,a_1), ... (a_n-1,a_n), (a_n, +∞)
// the real interval's length is n+1
observingInterval: number[],
// Left means interval is Left closed right open interval
// Right means interval is Left open right closed interval
// Default is Right
inclusive?: "Left" | "Right",
// When scroll accross an,call this function
// The argument means that it is scrolled to interval (a_n-1,a_n)
onScrolledInterval: (n: number) => void,
}) => {
if (context.entity instanceof Panel) {
const panel = context.entity;
panel.addOnRenderFinishedCallback(() => {
(argument as any).scrollable = viewIdChains(argument.scrollable);
(argument as any).onScrolledInterval = context.function2Id(argument.onScrolledInterval);
context.callNative("coordinator", "observeScrollingInterval", argument)
});
}
},
}
}
12 changes: 11 additions & 1 deletion doric-web/dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion doric-web/dist/index.js.map

Large diffs are not rendered by default.

0 comments on commit 52e5977

Please sign in to comment.